Commit Graph

10224 Commits

Author SHA1 Message Date
Crowdin Bot dfd959be4e New Crowdin translations by GitHub Action 2026-03-26 23:11:00 +00:00
Vitor Pamplona 75a8e461ad 20x Faster Rfc3986Normalizer and way less objects being created. 2026-03-26 19:04:18 -04:00
Vitor Pamplona 7c8d44559e Benchmark for the new Rfc3986 Normalizer 2026-03-26 17:32:07 -04:00
Vitor Pamplona 395b16050b Try catch to avoid crashes 2026-03-26 17:31:32 -04:00
Vitor Pamplona 4cb5b63631 Speeding up DrawerContent 2026-03-26 15:56:01 -04:00
Vitor Pamplona e92d5c8a5c Simplifies navigation row 2026-03-26 15:48:47 -04:00
Vitor Pamplona 9cbcb3b39d Speedup rendering of the left bar by avoiding a textfield 2026-03-26 15:37:06 -04:00
Vitor Pamplona 85ebb7918b AsyncImage is faster than Image for resources 2026-03-26 15:22:03 -04:00
Vitor Pamplona 5d256bab2c stable subs 2026-03-26 15:21:08 -04:00
Vitor Pamplona 9171209d44 Kickstart LRUCache to void constructor blocking in main thread 2026-03-26 15:20:49 -04:00
Vitor Pamplona 3ecf761d68 Removes logs from animation 2026-03-26 14:37:43 -04:00
Vitor Pamplona 39e89834ba Moves gesture enable to inside the composable.
Creates a function just for navhost
2026-03-26 14:37:16 -04:00
Vitor Pamplona bba4d28e4b stable toast manager 2026-03-26 14:35:31 -04:00
Vitor Pamplona d0a3679778 Minimizes the size of the banner 2026-03-26 14:35:18 -04:00
Vitor Pamplona 423bc04dba Fixes logging 2026-03-26 13:54:46 -04:00
Vitor Pamplona 9f7672249b Otherwise, it is created by the main thread when the AccountViewModel Factory is run 2026-03-26 13:54:33 -04:00
Vitor Pamplona 79d66cca8f Merge pull request #1952 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-26 11:41:15 -04:00
Crowdin Bot 7cb9cc6cd5 New Crowdin translations by GitHub Action 2026-03-26 15:37:20 +00:00
Vitor Pamplona 7d6f1a539f Merge branch 'main' of https://github.com/vitorpamplona/amethyst
* 'main' of https://github.com/vitorpamplona/amethyst:
  New Crowdin translations by GitHub Action
  update translations: CZ, DE, PT, SE
  fix: restore local WatchAndDisplayNip05Row in ShowUserSuggestionList
  refactor: remove Namecoin label from search results
  feat: show Namecoin label on .bit search results without ViewModel state
  refactor: remove Namecoin label from search results per review
  refactor: simplify .bit search resolution per review feedback
  feat: resolve bare .bit domains and show Namecoin resolution status in UI
  New Crowdin translations by GitHub Action
  New Crowdin translations by GitHub Action
  refactor: rename trustAllCerts → usePinnedTrustStore
  fix: harden TLS for GrapheneOS and security-conscious Android ROMs
  doc: verify .onion ElectrumX cert via Tor, document pinning
  fix: bypass cert pinning for .onion ElectrumX servers
  feat: TOFU cert pinning for custom ElectrumX servers
  feat: add Test Connection diagnostics to Namecoin settings
  fix: pin ElectrumX server certs instead of trust-all TrustManager

# Conflicts:
#	amethyst/src/main/java/com/vitorpamplona/amethyst/AppModules.kt
#	amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt
2026-03-26 11:34:54 -04:00
Vitor Pamplona 155e57ab11 Defers most module creations to when they are needed via lambdas 2026-03-26 11:11:44 -04:00
Vitor Pamplona 7952f558eb Parallelizes the JSON parsing from stored account. 2026-03-26 11:11:21 -04:00
Vitor Pamplona 958a460ea9 Adds a try/catch to make sure this procedure unsubscribes from the req 2026-03-26 11:10:45 -04:00
Vitor Pamplona 3776f65179 Defers the creation of the geohashStateFlow until needed 2026-03-26 11:08:27 -04:00
Vitor Pamplona 44c39b01ea Defers NIP05 Resolver/NamecoinResolver Builder until needed 2026-03-26 11:07:56 -04:00
Vitor Pamplona d73dd662c6 Reduces calculations and state creations in the NavHost builder 2026-03-26 11:03:07 -04:00
Vitor Pamplona 4ef1ba1ac6 Fixes the bug of not sending NIP-17 reactions in the complete UI mode 2026-03-26 09:25:09 -04:00
Vitor Pamplona 276dc6589c Merge pull request #1937 from mstrofnone/fix/samsung-oneui7-namecoin-tls
fix: pin ElectrumX server certs for Samsung One UI 7 (Android 16) compatibility
2026-03-26 09:14:30 -04:00
Vitor Pamplona f9c381a113 Merge pull request #1951 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-26 08:38:12 -04:00
Crowdin Bot b77e6c1b6c New Crowdin translations by GitHub Action 2026-03-26 10:57:57 +00:00
davotoula 17eea1dca9 update translations: CZ, DE, PT, SE 2026-03-26 11:53:59 +01:00
M 7293b0985b fix: restore local WatchAndDisplayNip05Row in ShowUserSuggestionList
The local private WatchAndDisplayNip05Row uses NonClickableObserveAndDisplayNIP05
(plain text domain), while the shared one in ShowQRScreen uses the clickable
ObserveAndDisplayNIP05. They are not the same function — restore the local copy
to preserve the correct non-clickable behavior in user suggestions.
2026-03-26 17:36:53 +11:00
nrobi144 9c9c7d3f24 feat(cache): seed NotificationsScreen from cache on compose
- Add localCache param to NotificationsScreen
- Seed reactions and zaps from cache on initial compose
- Notifications now persist across tab navigation
- All screens now have cache seeding (Feed, Thread, Profile,
  Bookmarks, Reads, Notifications)
2026-03-26 07:20:22 +02:00
nrobi144 072e437277 feat(cache): wire State classes on DesktopIAccount for GC retention
- Add BookmarkListState, Kind3FollowListState, Nip65RelayListState
  to DesktopIAccount — pins important AddressableNotes via strong refs
- Create stub Kind3FollowListRepository + Nip65RelayListRepository
  (no persistence yet, null backups)
- Update followingKeySet() to read from Kind3FollowListState.flow
- Revert accidental long-form branch changes in DeckColumnContainer
2026-03-26 07:17:39 +02:00
nrobi144 2b95cc013a feat(cache): extract Kind3FollowListState + Nip65RelayListState to commons
- Add Kind3FollowListState to commons/commonMain with ICacheProvider
  + Kind3FollowListRepository interface for settings needs
- Add Nip65RelayListState to commons/commonMain with ICacheProvider
  + Nip65RelayListRepository interface with default relay sets
- Per-feature repository interfaces match existing EphemeralChatRepository
  / PublicChatListRepository pattern in commons
- Android originals unchanged — Desktop will use commons versions
- Static LocalCache.justConsumeMyOwnEvent calls replaced with cache param
2026-03-26 07:14:16 +02:00
nrobi144 7151d3052a feat(cache): extract BookmarkListState to commons/commonMain
- Move BookmarkListState from amethyst/ to commons/commonMain/
- Change cache param from LocalCache to ICacheProvider
- Android file becomes typealias to commons version
- No settings or decryptionCache dependencies (simplest State class)
- Pins bookmarkList AddressableNote via strong ref for GC retention
2026-03-26 07:14:16 +02:00
nrobi144 cf6a74b162 feat(cache): add periodic memory cleanup for Desktop
- Add cleanMemory() to DesktopLocalCache (sweeps stale WeakRef entries)
- Add startCleanupLoop() to Coordinator with heap monitoring
  (MemoryMXBean, checks every 30s, cleans at >75% heap or every 5min)
- cleanObservers() clears unused NoteFlowSets on notes + addressables
- Try-catch per operation so one failure doesn't skip the rest
- 2-minute startup grace period before first cleanup
- Cleanup job cancelled on clear() (account switch / logout)
2026-03-26 07:14:15 +02:00
nrobi144 3dbbc039b3 feat(cache): replace BoundedLargeCache with LargeSoftCache on Desktop
- DesktopLocalCache now uses LargeSoftCache (WeakReference-based, GC-driven)
  instead of BoundedLargeCache (strong refs, 50k cap, arbitrary eviction)
- Delete BoundedLargeCache.kt — no longer needed
- Rewrite findUsersStartingWith to use forEach instead of values()
- Remove BoundedLargeCache eviction tests (no longer applicable)
- Notes now only disappear when nothing references them, not arbitrarily

Per Vitor's feedback: "this maximum size approach might not work well,
as things will just disappear"
2026-03-26 07:13:27 +02:00
nrobi144 00b06a0e2a refactor(cache): move LargeSoftCache to commons/jvmAndroid, fix ICacheProvider types
- Move LargeSoftCache from amethyst/model to commons/jvmAndroid/model/cache
  so both Android and Desktop share the same WeakReference cache implementation
- Change ICacheProvider return types from Any? to proper types (User?, Note?)
  since these model classes already live in commons
- Remove unnecessary casts in ThreadAssembler, ChatNewMessageState, SearchBarState
- Improve LargeSoftCache.cleanUp() to use single-pass iterator (zero allocation)
- Update Android imports in LocalCache, LargeSoftCacheAddressExt, and test

Per Vitor's feedback on PR #1905: BoundedLargeCache evicts arbitrarily.
LargeSoftCache uses WeakReferences so GC respects the reference graph.
2026-03-26 07:13:27 +02:00
nrobi144 3b489fb3cb feat(cache): seed Reads and Bookmarks screens from cache on compose
Both screens now show cached data instantly on navigation instead of
showing loading states while re-fetching from relays.

- BookmarksScreen: reads cached BookmarkListEvent from addressableNotes,
  seeds public bookmark events from notes cache
- ReadsScreen: seeds long-form notes (kind 30023) from notes cache

Relay subscriptions still run to fetch fresh data in parallel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:27 +02:00
nrobi144 f27c8811d5 fix(cache): don't reset followersCount to 0 on subscription restart
Cached value now stays visible until relay data exceeds it, preventing
the count jumping from cached→0→ticking back up on each navigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:27 +02:00
nrobi144 f2169e0236 feat(cache): cache profile metadata and follower/following counts
Profile screen now reads initial values from cache so navigating back
shows data instantly instead of re-fetching everything from scratch.

- Seed displayName/about/picture from User.metadataOrNull() on compose
- Add followerCounts/followingCounts maps to DesktopLocalCache
- Write counts on each update, read on profile open
- Follower count still ticks up live (good UX) but starts from cached value
- 4 new tests for profile count caching + metadata cache reads

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:27 +02:00
nrobi144 3e41bab5d5 fix(cache): use relayStatuses (available) instead of connectedRelays for subscriptions
Root cause of "0 relays, 0 notes, 0 follows": all screens used
connectedRelays as the relay set for subscriptions, but NostrClient
uses relay-on-demand — relays only connect when openReqSubscription
is called with their URL. This created a deadlock: screens waited for
connected relays, but relays only connect when screens subscribe.

Fix: use relayStatuses.keys (registered/available relays) which are
populated by addDefaultRelays() at startup. openReqSubscription
triggers connection on-demand.

Affected screens: FeedScreen, UserProfileScreen, ThreadScreen,
NotificationsScreen, BookmarksScreen, ReadsScreen, NewDmDialog.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:27 +02:00
nrobi144 1e1bc1b172 fix(cache): add missing relay subscriptions for FeedScreen and UserProfileScreen
FeedScreen and UserProfileScreen used DesktopFeedViewModel (cache-backed)
but never subscribed to relays for kind 1/kind 3 events, causing 0 notes,
0 followed, and 0 relays on the home feed.

Adds rememberSubscription calls for:
- Contact list (kind 3) in FeedScreen → populates followedUsers
- Global/following feed (kind 1) in FeedScreen → populates cache
- Profile notes (kind 1) in UserProfileScreen → populates cache

Also adds 33 integration tests covering the full cache pipeline:
- DesktopCachePipelineTest: cache → filter → ViewModel (25 tests)
- CoordinatorPipelineTest: coordinator → cache → ViewModel (8 tests)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:26 +02:00
nrobi144 0621e8f7c2 refactor(cache): P3 simplifications — remove dead code, reduce abstractions
- Replace SubscriptionHealth map + data class with single lastEventAt
  Long? timestamp (only consumer was RelayHealthIndicator taking max())
- Replace consumer HashMap registry with when block (safe casts,
  compiler-checked, 9 kinds doesn't benefit from O(1) lookup)
- Remove dead loadReactionsForNotes() (superseded by requestInteractions)
- Remove unused BoundedLargeCache methods: containsKey, isEmpty,
  mapNotNull, forEach (zero external callers)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:26 +02:00
nrobi144 4f5665a2bd fix(cache): address review findings — subscription churn, O(n) size, atomicity
P1 fixes from compound engineering review:
- Fix subscription churn flooding relays: DisposableEffect keyed on
  feedMode/noteId (stable) instead of feedState (changes every 250ms)
- BoundedLargeCache: AtomicInteger counter replaces O(n)
  ConcurrentSkipListMap.size() — eliminates 50K traversal per event
- Non-atomic updateHealth(): use MutableStateFlow.update{} for
  atomic compare-and-set instead of read-modify-write race

P2 fixes:
- DesktopThreadFilter: LinkedHashSet for O(1) containment checks,
  down from O(R²) with MutableList
- consumeContactList: createdAt guard ensures newer events always win
- consumeEvent error logging: include event ID and relay URL

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:26 +02:00
nrobi144 c598c6135c feat(cache): ThreadScreen → DesktopFeedViewModel + DesktopThreadFilter
Replace EventCollectionState + 7 rememberSubscription blocks + inline
count maps with DesktopFeedViewModel + DesktopThreadFilter (graph walk).
Keep root note + replies relay subscriptions to populate cache. Use
FeedNoteCard for both root and reply notes (reads counts from Note.flowSet).
Remove ~200 lines of inline state management (zapsByEvent, reactionIdsByEvent,
replyIdsByEvent, repostIdsByEvent, bookmarkList, bookmark subscription).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:26 +02:00
nrobi144 8c1e54e147 feat(ui): relay health indicator in NavigationRail
Add RelayHealthIndicator component — shows elapsed time since last
relay event. Hidden when <30s (healthy), shows "45s ago" / "3m ago"
when stale. Placed above BunkerHeartbeatIndicator in NavigationRail.
Reads from Coordinator's subscriptionHealth StateFlow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:26 +02:00
nrobi144 50eb03bc3e feat(cache): UserProfileScreen notes feed → DesktopFeedViewModel
Replace EventCollectionState + createUserPostsSubscription + manual cache
hydration with DesktopFeedViewModel + DesktopProfileFeedFilter. Profile
header subscriptions (metadata, contact list, followers) kept as-is since
they're not feed concerns. DisposableEffect cleanup on profile switch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:26 +02:00
nrobi144 c63ace1d9c feat(cache): FeedScreen → DesktopFeedViewModel + Note-based FeedNoteCard
Rewrite FeedScreen from inline EventCollectionState + 8 rememberSubscription()
calls to cache-centric DesktopFeedViewModel pattern:

- ViewModel keyed on feedMode with DisposableEffect cleanup (destroy())
- FeedState pattern matching (Loading/Loaded/Empty/Error)
- FeedNoteCard takes Note instead of Event, reads counts from Note.flowSet
- DisposableEffect for note.clearFlow() cleanup in LazyColumn
- DisposableEffect for Coordinator interaction subscription lifecycle
- LaunchedEffect for rate-limited metadata loading via Coordinator
- Extract FeedHeader into separate composable
- Add destroy() to DesktopFeedViewModel (ViewModel.clear() is internal in KMP)
- Update UserProfileScreen to look up Note from cache for FeedNoteCard

Removes ~350 lines of inline state management (EventCollectionState,
zapsByEvent, reactionIdsByEvent, replyIdsByEvent, repostIdsByEvent,
followedUsers, bookmarkList, 8 rememberSubscription blocks).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:26 +02:00
nrobi144 e8ede21c17 feat(cache): Coordinator error handling + interaction subscriptions
Add try-catch in consumeEvent() so one bad event doesn't kill the
pipeline. Add requestInteractions()/releaseInteractions() with Job
tracking via ConcurrentHashMap for screen-scoped subscription lifecycle.
Add SubscriptionHealth tracking (lastEventReceivedAt, eoseReceived)
exposed as StateFlow for UI consumption.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 07:13:25 +02:00