Commit Graph

68 Commits

Author SHA1 Message Date
nrobi144 5661c6df27 fix(desktop): clear stored credentials on logout
All user-initiated logouts now pass deleteKey=true to remove
nsec from secure storage, clear last_npub, and delete bunker state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:16:09 +02:00
nrobi144 26ea0be4c7 fix(desktop): simplify settings logout to just a button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:16:09 +02:00
nrobi144 2346d92f16 feat(desktop): add logout option to menu bar and settings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:16:09 +02:00
nrobi144 1821b9ff71 test: add NIP-46 test suite for desktop, quartz, and fix pre-existing chess test errors
Add comprehensive test coverage for NIP-46 bunker login across quartz and desktopApp:

Quartz (4 files, 48 tests):
- ResponseParserTest: all 7 response parsers (success/error/unexpected)
- FromBunkerUriTest: URI parsing, validation, edge cases
- ConvertExceptionsTest: SignerResult→Exception mapping
- NostrConnectEventTest: canDecrypt, talkingWith, verifiedRecipientPubKey

Desktop (6 files, 45 tests):
- BunkerUriUtilsTest: validateBunkerUri + stripBunkerSecret
- AccountManagerKeyLoginTest: nsec/npub/invalid login, save, generate
- AccountManagerLogoutTest: logout, forceLogout, state transitions
- AccountManagerLoadAccountTest: internal/bunker/missing-key scenarios
- AccountManagerBunkerLoginTest: hasBunkerAccount, setConnectingRelays
- AccountManagerHeartbeatTest: start/stop, no-crash with internal signer

Production changes:
- AccountManager: constructor private→internal, add homeDir param for test injection, extract stripBunkerSecret to internal top-level, constants internal
- desktopApp/build.gradle.kts: add mockk test dependency

Fix pre-existing chess test compilation errors:
- ChessStateReconstructorTest: add missing jester subpackage imports
- ChessGameEventTest: altText()→alt() + add nip31Alts import

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:16:09 +02:00
nrobi144 6c24c52104 feat(desktop): add NIP-46 remote signer (bunker://) login
Support bunker:// URI login for desktop, enabling private key delegation
to remote signers (nsec.app, Amber). Includes heartbeat monitoring,
force-logout on revocation, and ConnectingRelays startup state.

- AccountManager: bunker login/save/load, heartbeat ping, force logout
- LoginCard: auto-detect bunker:// URI, validation, connecting state
- LoginScreen: wire bunker callback, ConnectingRelays screen
- Main.kt: relay timeout, error recovery, scope cleanup, data objects
- ForceLogoutDialog: alert on signer revocation/disconnect

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:15:24 +02:00
Vitor Pamplona 2387a1bb91 Improves the order of search results 2026-03-09 11:25:00 -04:00
Vitor Pamplona e6e697a5f8 Adds the full list of URLs to the Desktop app 2026-03-07 16:54:47 -05:00
Vitor Pamplona 9abd61e2de Improves package layout for nip64 chess 2026-03-04 09:25:38 -05:00
Vitor Pamplona 4060bef2be Lint 2026-03-04 09:19:21 -05:00
Vitor Pamplona ad578b394d Merge pull request #1759 from vitorpamplona/claude/refactor-nip64chess-structure-3iFIB
refactor: restructure nip64Chess to match nip88Polls pattern
2026-03-04 08:30:35 -05:00
nrobi144 db530a6820 fix(desktop): audit fixes for deck layout
Critical:
- GlobalFeed now renders global feed (was identical to HomeFeed)
- DeckState uses atomic _columns.update{} instead of non-atomic .value=
- lastKnownWidth marked @Volatile for thread safety

Medium:
- save() debounced 500ms via coroutine (was sync disk I/O per drag frame)
- Width redistribution fills gaps after clamping on column remove
- Hashtag column pre-fills search query
- ColumnNavigationState.stack exposed as StateFlow not MutableStateFlow
- Settings column deduped (focuses existing instead of adding duplicate)
- Exceptions logged in save/load instead of silently swallowed

Low:
- Thread column icon fixed (was Home, now Article)
- Drag divider hit target widened to 12dp (visual stays 4dp)
- Horizontal scroll added for column overflow
- Auto-fit columns on first composition / window resize
- Column shortcuts limited to actual column count
- Deterministic default column IDs
- Overlay fallback shows message instead of blank

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 10:02:22 +02:00
nrobi144 73b8059b55 feat(desktop): collapsible info panel in chess deck column
Hide GameInfo/MoveHistory/Actions panel by default in deck view
with a chevron toggle to expand. Add Chess to AddColumnDialog.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:45:01 +02:00
nrobi144 991ac3b31b merge: integrate upstream main with chess PR #1702
Resolves merge conflicts in Main.kt, adds Chess column type
to deck layout (DeckColumnType, ColumnHeader, DeckColumnContainer,
DeckState, SinglePaneLayout, View menu). Updates DesktopMessagesScreen
calls for new relayManager/localCache params.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:33:44 +02:00
Claude 2df8a106d4 refactor: restructure nip64Chess to match nip88Polls pattern
Reorganize nip64Chess event classes into individual packages with
dedicated tag classes, TagArrayBuilderExt, and TagArrayExt files,
following the same structure used by nip88Polls.

New package structure:
- challenge/ - LiveChessGameChallengeEvent with PlayerColorTag, TimeControlTag
- accept/ - LiveChessGameAcceptEvent with ChallengeEventTag
- move/ - LiveChessMoveEvent with GameIdTag, MoveNumberTag, SanTag, FenTag
- end/ - LiveChessGameEndEvent with ResultTag, TerminationTag, WinnerTag
- draw/ - LiveChessDrawOfferEvent
- game/ - ChessGameEvent (Kind 64)
- jester/ - JesterEvent, JesterProtocol, JesterContent, JesterGameEvents

Each tag class follows the companion object pattern with isTag(),
parse(), and assemble() methods. Each event package includes
TagArrayBuilderExt for building and TagArrayExt for parsing.

https://claude.ai/code/session_01Qtzhka3p5N3Hbns4xrRbsv
2026-03-04 00:51:43 +00:00
nrobi144 afe126f393 feat(desktop): add single-pane/deck toggle with smart column resizing
- Add LayoutMode enum (SINGLE_PANE/DECK) persisted in DesktopPreferences
- SinglePaneLayout: NavigationRail + single content area reusing deck routing
- View menu "Deck Layout" toggle with Cmd+Shift+D shortcut
- Column resize: redistribute width on add/remove, double-click header to expand
- Constrain drag resize to window bounds via BoxWithConstraints
- FlowRow headers in FeedScreen/ReadsScreen to wrap on narrow columns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 17:38:32 +02:00
davotoula 59309c2b1d remove unused imports 2026-03-02 15:53:21 +00:00
Vitor Pamplona b523505c05 fixes spotless check 2026-02-24 18:00:04 -05:00
Vitor Pamplona b1fd450c91 Merge branch 'main' into feat/desktop-private-dms 2026-02-24 17:50:48 -05:00
nrobi144 e7239980c6 feat(desktop): add multi-column deck layout replacing NavigationRail
Replace the 80dp NavigationRail + single content area with a TweetDeck-style
multi-column deck. Default layout: Home Feed + Notifications + Messages.

New deck system:
- DeckColumnType sealed class with 12 column types
- DeckState with StateFlow-based column management
- Per-column navigation stack for in-column drill-down
- Draggable dividers for column resize (300-800dp)
- Column config persisted via Jackson JSON in DesktopPreferences
- 48dp thin sidebar with add-column and settings buttons
- AddColumnDialog for picking column types

Keyboard shortcuts:
- Cmd+T: Add column
- Cmd+W: Close focused column
- Cmd+1-9: Focus column by index
- Cmd+Shift+Left/Right: Move column left/right

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:53:31 +02:00
nrobi144 78aa7962e9 feat(desktop): add DM broadcast status banner and audit fixes
- Show relay confirmation URLs in broadcast banner
- Add relayUrls field to DmBroadcastStatus.Sent
- Wire send progress tracking with per-relay confirmations
- Fix empty chatroom Loading state transition
- Improve NewDmDialog npub metadata resolution
- Harden sendAndWaitForResponse timeout handling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 06:53:53 +02:00
nrobi144 35a15f0462 feat(desktop): add DM broadcast banner and fix empty room loading
- Fix ListChangeFeedViewModel stuck on Loading for empty chatrooms by
  adding invalidateData() call in init block
- Add DmBroadcastStatus sealed class and DmBroadcastBanner composable
  in commons for relay send progress display
- Add DmSendTracker using sendAndWaitForResponse for confirmed delivery
- Wire send tracking through DesktopIAccount into ChatPane banner
- Fix audit risks: unsubscribe DMs on account change, wait for relay
  connect before subscribing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 12:20:04 +02:00
nrobi144 5d983c5d27 fix(desktop): wire gift wrap broadcast for DM reactions
The sendWrappedReaction function was creating NIP-17 gift wraps via
NIP17Factory but never broadcasting them. Added sendGiftWraps() to
IAccount interface with implementations in both Desktop and Android.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:34:33 +02:00
nrobi144 3f5ad8f7be feat(desktop): wire NIP-17 emoji reactions in DM chat
Replace TODO stub with sendWrappedReaction using NIP17Factory.
createReactionWithinGroup creates gift-wrapped reactions for group privacy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 07:34:53 +02:00
nrobi144 9a30b935d2 feat(desktop): wire DM sending, subscriptions, and new DM dialog
- DesktopIAccount: sign + broadcast NIP-04/NIP-17 messages via relay layer
- Main.kt: activate DM subscriptions on login, consume events into cache
- NewDmDialog: user search dialog with SearchBarState + UserSearchCard
- DesktopMessagesScreen: wire Cmd+Shift+N and "+" button to NewDmDialog

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 07:33:04 +02:00
Vitor Pamplona 2c3ca7f906 - Finishes the transition to EventHint objects for building events.
- Removes the "a-tag" dependency on Addressable interface because the `a` can have different names in different objects.
2026-02-18 10:45:50 -05:00
nrobi144 5d81da2486 feat(desktop): add encrypted DMs with split-pane layout (NIP-04/NIP-17)
Full desktop DM implementation with shared components extracted to commons:
- Relay layer: DM relay state, filter construction, subscription coordinator
- Shared: ChatroomFeedFilter, ChatroomFeedViewModel, ChatNewMessageState
- Shared UI: ChatBubbleLayout, ChatMessageCompose, ChatroomHeader, ChatTheme
- Desktop: split-pane (conversation list + chat), keyboard shortcuts, hover reactions
- IAccount extended with signer, sendNip04/17, chatroomList, isAcceptable

Refs: vitorpamplona/amethyst#1704

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:19:46 +02:00
nrobi144 5f15f0c3b1 fix: address Copilot review comments
- ChessPosition: include all fields in equals/hashCode
- AcceptedGamesRegistry: add thread safety with synchronized
- ChessEventBroadcaster: use valid filter for connection trigger
- ChessEventBroadcaster: fix misleading relayResults
- Remove println debug logging from ChessSubscription/Broadcaster
- UserProfileScreen: use proper JSON parsing via MetadataEvent

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 16:39:24 +02:00
nrobi144 8d098cf86d feat(chess): focused polling, promotion fix, and game end celebration
- Add focused game mode to ChessPollingDelegate: when viewing a game,
  only that game is polled instead of all active games
- Fix pawn promotion by parsing promotion suffix in publishMove
  (e.g., "e8q" -> "e8" + QUEEN)
- Add game end overlay with victory/defeat/draw celebration
- Remove all debug println statements for production readiness

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 12:14:34 +02:00
nrobi144 3c89c442bc feat(chess): add slim ViewModels and shared broadcast banner (Steps 7-10)
Step 7: ChessViewModelNew.kt - Slim Android ViewModel (~130 lines)
- Delegates all business logic to ChessLobbyLogic
- Exposes StateFlows from logic.state
- Platform adapter creation only

Step 8: DesktopChessViewModelNew.kt - Slim Desktop ViewModel (~120 lines)
- Same pattern as Android, delegates to ChessLobbyLogic
- UserMetadataCache for profile display
- External CoroutineScope injection

Step 9: ChessBroadcastBanner.kt - Shared Compose banner in commons
- Uses ChessBroadcastStatus from ChessLobbyState
- Works on both Android and Desktop via Compose Multiplatform
- Shows broadcasting progress, sync status, errors

Step 10: UI consumers ready for migration
- New ViewModels use ChessChallenge (enriched display data)
- Shared banner ready to replace Android-only ChessStatusBanner
- Existing screens continue to work with old ViewModel

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 12:14:34 +02:00
nrobi144 42b33ca04c feat(chess): add platform adapters and enhance lobby state (steps 5-6)
- Add ChessLobbyState with completedGames, replaceGameState(), moveToCompleted()
- Add challengerAvatarUrl to ChessChallenge
- Add CompletedGame data class for game history

Platform Adapters:
- AndroidChessAdapter: AndroidChessPublisher, AndroidRelayFetcher, AndroidMetadataProvider
- DesktopChessAdapter: DesktopChessPublisher, DesktopRelayFetcher, DesktopMetadataProvider

Shared Infrastructure:
- ChessRelayFetchHelper for one-shot relay queries
- IUserMetadataProvider interface for platform-specific metadata
- ChessFilterBuilder with simple filter methods for fetchers
- ChessSubscriptionController interface for subscription management

Fix ChessSubscription.kt to remove broken dataSources().chess reference
(subscriptions now managed by ChessLobbyLogic)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 12:14:34 +02:00
nrobi144 e0d0e33408 refactor impl 2026-02-10 12:14:05 +02:00
Vitor Pamplona eb66182211 - Updates several libraries
- Reformats code to the newest Klint
- Fixes isEmpty bug on Filters
2026-02-09 14:06:07 -05:00
Vitor Pamplona 710f15f790 - Fixes copyright using KDoc patterns instead of simpler comments
- Moves spotless and git-hooks to hidden folders
2026-02-09 13:06:41 -05:00
Vitor Pamplona 4e39a531b7 Moves metadata methods from User to UserCache object 2026-02-07 10:18:13 -05:00
Vitor Pamplona 4ced055035 Switches the metadata relay for the relay being used with the most amount of posts to be the relayhint 2026-02-04 17:38:01 -05:00
Vitor Pamplona e6f7a543cd Migrates Desktop App to the new metadata cache. 2026-02-04 15:38:16 -05:00
Vitor Pamplona c3f09987aa Merge pull request #1676 from nrobi144/nrobi144/phase-2A
Desktop: Basic Search + Bookmarks + Zaps
2026-01-26 09:53:35 -05:00
nrobi144 71e68dc35b refactor(commons): migrate from Moko to Compose Multiplatform Resources
Remove Moko Resources dependency that blocks AGP 9.0 migration.
Migrate to built-in Compose Multiplatform Resources which is compatible
with the new KMP Android plugin.

- Remove moko-resources plugin and libraries from commons module
- Move strings.xml from moko-resources/ to composeResources/values/
- Update imports from SharedRes.strings.* to Res.string.*
- Add compose.components.resources dependency to desktopApp
- Configure resource package as com.vitorpamplona.amethyst.commons.resources

Closes #1675

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 13:29:55 +02:00
nrobi144 ff47080cf1 fix: Resolve API mismatches after merge with upstream
- Fix import paths to use desktop.subscriptions instead of commons.subscriptions
- Update DesktopLocalCache to match ICacheProvider interface changes
- Use correct commons.relayClient paths for ComposeSubscriptionManager
- Add missing justConsumeMyOwnEvent and getOrCreateAddressableNote methods

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:23:58 +02:00
nrobi144 d08aed47e8 Merge upstream/main into nrobi144/phase-2A
Resolved import conflicts caused by package reorganization:
- upstream moved classes to amethyst/service/relayClient/*
- upstream moved models to commons/model/*
- kept our desktop additions (zaps, bookmarks, search)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:04:13 +02:00
nrobi144 8155cfee9d update metadata loading 2026-01-20 15:18:11 +02:00
nrobi144 8f6de1d304 zap updates 2026-01-19 16:32:01 +02:00
davotoula 505a6583ee remove unused imports 2026-01-15 14:20:05 +01:00
Vitor Pamplona 04ac40fa1a moves test as well 2026-01-13 16:07:03 -05:00
Vitor Pamplona 09d0f4425c Moves some of the stuff that was saved in Commons back to the desktop app because it is only used there 2026-01-13 16:04:02 -05:00
nrobi144 e1412c1f97 fix: Add proper empty states with EOSE tracking
- NotificationsScreen: Show "No notifications yet" after EOSE instead of infinite loading
- FeedScreen: Show "No notes found" after EOSE for both Global and Following feeds
- ThreadScreen: Show "Note not found" if root note missing after EOSE, "No replies yet" for empty threads

Uses existing EmptyState component from commons. Tracks EOSE (End of Stored Events) from relays to distinguish between "still loading" and "no data".

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 06:52:33 +02:00
nrobi144 45207857c6 finish ThreadScreen 2026-01-12 06:23:57 +02:00
Vitor Pamplona cba4d25424 Moves follows and publish to their own packages 2026-01-07 16:16:01 -05:00
Vitor Pamplona 60dafd9267 Moves reactions to packages for their nips 2026-01-07 13:26:47 -05:00
nrobi144 a9141763e1 previous PR fixes 2026-01-07 07:12:00 +02:00