Commit Graph

10898 Commits

Author SHA1 Message Date
Crowdin Bot 4595613fa4 New Crowdin translations by GitHub Action 2026-04-06 23:44:58 +00:00
Crowdin Bot ae142a39cd New Crowdin translations by GitHub Action 2026-04-06 20:23:10 +00:00
Vitor Pamplona 7e991fd4d8 Merge pull request #2164 from vitorpamplona/claude/fix-old-call-ringing-nM8y5
Prevent stale call offers from retriggering after app restart
2026-04-06 16:21:36 -04:00
Claude 5731275362 fix: prevent old call events from triggering ringing after app restart
When the app restarts and reconnects to relays, old call offer events
from completed calls could be replayed, causing the phone to ring for
calls that already ended. This was especially noticeable when the user
killed and restarted the app shortly after a call.

Three protections added to CallManager:

1. Track completed call IDs: hangup/reject events mark their call-id as
   completed. Subsequent offer events for the same call-id are ignored.

2. Init timestamp guard: events created before the CallManager was
   initialized (minus a grace period) are rejected, preventing stale
   events from a previous app session from triggering ringing.

3. Completed call IDs survive reset(): the set is intentionally not
   cleared when the call state machine resets to Idle, ensuring that
   stale offers remain blocked for the lifetime of the CallManager.

https://claude.ai/code/session_0145VKiG8yZMqcMsaBEjNPxv
2026-04-06 20:15:26 +00:00
Vitor Pamplona 96fd58dfcd Merge pull request #2163 from vitorpamplona/claude/fix-webrtc-ringing-bug-pNe68
Fix audio cleanup and call state handling on Activity destroy
2026-04-06 15:30:45 -04:00
Claude 6486a0a995 fix: stop ringing immediately when caller cancels WebRTC call
Move transitionToEnded() before the signing + relay publish in hangup()
so the UI stops ringing/ringback immediately, matching the pattern
already used by rejectCall(). Add onDestroy safety net in CallActivity
to hang up if the Activity is destroyed while a call is active. Wrap
audio stop methods in try-catch to prevent one failure from blocking
the others.

https://claude.ai/code/session_01Rip2HPCbF48PPFDiB2X5ik
2026-04-06 19:29:36 +00:00
Vitor Pamplona 121eabd51f Merge pull request #2161 from vitorpamplona/claude/add-relay-drag-drop-uFrmj
Add drag-to-reorder functionality for relay lists
2026-04-06 15:10:28 -04:00
Vitor Pamplona 2b200538f0 Adjusting elevation borders 2026-04-06 15:07:08 -04:00
Claude 8a64e218b8 fix: prevent double-swap ping-pong during relay drag
After swapping with an adjacent item, the dragOffset adjustment can
flip its sign (e.g. negative becomes positive), which immediately
triggers the second if-block to swap back in the opposite direction
within the same onDrag call. This causes the dragged item to jump
and the user to end up dragging a different item. Fix by returning
after each successful swap so only one swap occurs per drag event.

https://claude.ai/code/session_01RVM5kEJGrCaJTaP3GmVHDd
2026-04-06 18:29:25 +00:00
Claude a092e78e8b fix: preserve relay order from event instead of sorting by bytes
Remove the sortedBy(receivedBytes) from relayListBuilder and
Nip65RelayListViewModel.clear() so relays keep their order as
stored in the Nostr event. This makes drag-and-drop reordering
meaningful since the saved order is now preserved on reload.

https://claude.ai/code/session_01RVM5kEJGrCaJTaP3GmVHDd
2026-04-06 18:15:21 +00:00
Claude cd860472ec fix: prevent drag gesture cancellation on item swap
When items swap during drag, the composable gets a new index value.
Using pointerInput(index) caused the gesture scope to restart, killing
the in-progress drag and leaving the UI stuck. Fix by using
rememberUpdatedState for the index so the pointerInput scope stays
alive across recompositions while always reading the current index.

https://claude.ai/code/session_01RVM5kEJGrCaJTaP3GmVHDd
2026-04-06 18:02:47 +00:00
Vitor Pamplona 4cda12b661 Merge pull request #2160 from vitorpamplona/claude/fix-webrtc-notification-permissions-wWe6i
Add permission handling for accepting calls from notifications
2026-04-06 13:17:05 -04:00
Claude 36d153150c fix: request microphone/camera permissions when accepting call from notification
When accepting an incoming WebRTC call via the notification's Accept
button, CallActivity now checks for RECORD_AUDIO and CAMERA permissions
before proceeding. If permissions are missing, the system permission
dialog is shown and the call is accepted only after permissions are
granted. This prevents the crash that occurred when accepting calls
from the notification without prior permission grants.

https://claude.ai/code/session_0193KQShzBh4puYh74dHgSbE
2026-04-06 16:38:32 +00:00
Claude 76899a417a fix: disable LazyColumn scroll during relay drag
Set userScrollEnabled = !isDragging on all LazyColumns that host
draggable relay items so the scroll gesture doesn't fight the drag
gesture. In AllRelayListScreen, scroll is disabled when any of the
12 category drag states is active.

https://claude.ai/code/session_01RVM5kEJGrCaJTaP3GmVHDd
2026-04-06 16:34:47 +00:00
Vitor Pamplona a649ab7b0e Merge branch 'main' of https://github.com/vitorpamplona/amethyst 2026-04-06 12:03:57 -04:00
Vitor Pamplona 5a36d0b7ae Code clean up and building a common parent class for WebRTC calls 2026-04-06 12:02:08 -04:00
Claude 5b95a47e0e refactor: keep lazy itemsIndexed for relay drag-and-drop
Replace the single-item Column approach with RelayDragState that works
within itemsIndexed. Each relay item remains a separate lazy item for
better performance with large lists. The drag handle icon on each row
captures drag gestures while the item modifier applies visual feedback
(elevation, scale, translation).

https://claude.ai/code/session_01RVM5kEJGrCaJTaP3GmVHDd
2026-04-06 15:29:19 +00:00
Vitor Pamplona da953ae9c3 Merge pull request #2159 from vitorpamplona/claude/add-danger-zone-section-PYwIs
Reorganize settings: move sensitive options to "Danger Zone" section
2026-04-06 11:17:11 -04:00
Claude 04dd2b5dce feat: add Danger Zone section to settings screen
Move Backup Keys, Request to Vanish, and Vanish History to a new
"Danger Zone" section at the bottom of the settings screen.

https://claude.ai/code/session_01UMEzMjGBZkTpNVebFA6XXN
2026-04-06 15:12:17 +00:00
Claude ce11edc352 feat: add drag-and-drop reordering to all relay list settings
Add DraggableRelayList composable with gesture-based drag-and-drop,
following the same pattern used in ReactionsSettingsScreen. Each relay
category (DM, NIP65 home/notif, search, blocked, trusted, local,
broadcast, indexer, proxy, private outbox, favorites) now shows a
drag handle and supports reordering via drag gestures.

https://claude.ai/code/session_01RVM5kEJGrCaJTaP3GmVHDd
2026-04-06 15:10:33 +00:00
Vitor Pamplona 2e3de795b6 Merge pull request #2158 from vitorpamplona/claude/fix-keypackage-status-jK921
Add KeyPackage publication status tracking for Marmot groups
2026-04-06 10:46:16 -04:00
Claude 66e6b0b726 fix: track KeyPackage published status and subscribe to own key packages
The publish KeyPackage button was always active because the app didn't
track whether a key package had already been published. This adds:

- hasActiveKeyPackages() to KeyPackageRotationManager and MarmotManager
- hasPublishedKeyPackage() to Account, checking both in-memory bundles
  and the local cache for existing kind:30443 events
- Own key package filter in MarmotSubscriptionManager and the EOSE
  manager so previously published key packages are downloaded from
  relays on app restart
- UI feedback: primary-colored key icon when published, contextual
  empty-state message, and a spinner during publishing

https://claude.ai/code/session_01BVe7aSEWd2KLi5Ks6RZkcc
2026-04-06 14:43:06 +00:00
Vitor Pamplona b1f54a5c07 Removing padding when 0 2026-04-06 10:28:21 -04:00
Vitor Pamplona 6251653951 Merge pull request #2157 from vitorpamplona/claude/clarify-keypackage-publishing-l9gb0
Refactor Marmot group chat UI with improved message composer
2026-04-06 10:20:20 -04:00
Claude a162f0d5cc feat: align Marmot chat message input with other chat screens
Replace the raw OutlinedTextField + IconButton Row with
ThinPaddingTextField, ThinSendButton, EditFieldBorder, and
EditFieldModifier to match the private DM and channel chat layouts.

https://claude.ai/code/session_013dhfy18dfuSYN8khXiLLBb
2026-04-06 14:17:57 +00:00
Claude 3e19143e2c feat: make FAB circular on Marmot Groups screen
Matches the CircleShape used by FABs on other screens.

https://claude.ai/code/session_013dhfy18dfuSYN8khXiLLBb
2026-04-06 14:16:06 +00:00
Claude 754568cf13 feat: add feedback when publishing KeyPackage on Marmot Groups screen
The publish KeyPackage button had no visual feedback, making it unclear
whether anything happened. Added a Snackbar to confirm success or show
errors, disabled the button during publishing, and updated the hint text
to direct users to the key icon.

https://claude.ai/code/session_013dhfy18dfuSYN8khXiLLBb
2026-04-06 14:13:52 +00:00
Vitor Pamplona 1d12ae36e5 Removing more warnings 2026-04-06 09:27:37 -04:00
Vitor Pamplona 014e08fa0d Fixes some warnings 2026-04-06 09:26:04 -04:00
Vitor Pamplona a1145e2a28 Fixing hex and time functions 2026-04-06 09:23:51 -04:00
Vitor Pamplona 5727d50fce Fixes test cases 2026-04-06 09:22:21 -04:00
Vitor Pamplona 2dc260d696 Switching icons to the new packages 2026-04-06 09:10:17 -04:00
Vitor Pamplona fb8802369f Merge pull request #2155 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-06 08:22:45 -04:00
Crowdin Bot f455d7338c New Crowdin translations by GitHub Action 2026-04-06 12:18:35 +00:00
Vitor Pamplona 2372af0b32 Merge pull request #2152 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-04-06 08:17:24 -04:00
Vitor Pamplona 814df2fd70 Merge pull request #2154 from vitorpamplona/claude/fix-polls-notification-bug-C4p48
Add periodic ticker to re-evaluate open polls after close date
2026-04-06 08:17:09 -04:00
Crowdin Bot 1f9ef8b560 New Crowdin translations by GitHub Action 2026-04-06 12:15:47 +00:00
Vitor Pamplona 9350dac3a1 Merge pull request #2151 from davotoula/claude/fix-share-dialog-autohide-XrQZk
fix: prevent share dialog from being dismissed by control auto-hide
2026-04-06 08:14:12 -04:00
Claude 7e32c314f4 fix: change poll re-evaluation ticker from 1 minute to 1 hour
https://claude.ai/code/session_01VY9FRuzHzwTVrePaJiHuHx
2026-04-06 12:11:55 +00:00
Claude 7d92386080 fix: prevent share dialog from being dismissed by control auto-hide
The share dialog in zoomable/fullscreen media view was auto-hiding
before users could select an option. This was caused by:

1. A 2-second timer in ZoomableContentDialog that hides all controls
   (including the share dialog) via AnimatedVisibility
2. A LaunchedEffect in RenderTopButtons that explicitly closed the
   share dialog whenever video controls auto-hid
3. Tap-to-toggle on the background also hiding controls while dialog
   was open

Fix: Hoist the share popup state and guard the auto-hide timer,
tap-to-toggle, and video control hide from dismissing when the
share dialog is open.

https://claude.ai/code/session_01YLujgxRDuujKCS3vgHc6Gq
2026-04-06 13:12:37 +02:00
Claude 7d0a234fd8 fix: remove expired polls from notification cards via periodic re-evaluation
The open polls notification flow only re-evaluated when new notes arrived
or dismissed IDs changed. Polls that passed their close date remained
visible until something else triggered the flow. Adding a 1-minute ticker
to the combine ensures expired polls are filtered out promptly.

https://claude.ai/code/session_01VY9FRuzHzwTVrePaJiHuHx
2026-04-06 02:33:49 +00:00
Vitor Pamplona a1c7d956ff Merge pull request #2150 from vitorpamplona/claude/improve-mls-implementation-y0mzv
Add comprehensive MLS test suite and improve GroupInfo signing
2026-04-05 20:39:07 -04:00
Claude 8379892078 feat: improve MLS implementation with comprehensive tests, docs, and bug fix
Add three new test files for the Marmot MLS implementation:

- MlsGroupLifecycleTest: End-to-end lifecycle tests covering Welcome
  processing, cross-member encrypt/decrypt, multi-member groups, commit
  processing, external joins, PSK proposals, and ReInit proposals.

- MlsGroupEdgeCaseTest: Security boundary tests for wrong epoch rejection,
  corrupted ciphertext detection, invalid KeyPackage rejection, out-of-range
  leaf indices, empty/large message handling, and add/remove/add cycles.

- MlsConformanceTest: Cross-implementation comparison tests verifying
  KeyPackage structure, GroupInfo signatures, Welcome message format,
  HPKE seal/open, SignWithLabel/VerifyWithLabel, LeafNode signatures,
  deterministic key schedule, and commit structure conformance.

Fix GroupInfo signature bug (RFC 9420 Section 12.4.3.1):
- buildWelcome() and groupInfo() were signing only groupContext.toTlsBytes()
  but verifySignature() checked against encodeTbs() which includes
  GroupContext + extensions + confirmationTag + signer. Now both methods
  build an unsigned GroupInfo first and sign its full TBS encoding.

Enhance MlsGroupManager KDoc with usage examples, responsibility breakdown,
and cross-implementation notes.

8 tests are @Ignore'd documenting a known bug: processCommit() does not
derive the same epoch secrets as commit(), causing cross-member AEAD
failures after epoch transitions.

https://claude.ai/code/session_018f67fqNReg3dEXcDimYLY1
2026-04-05 23:39:06 +00:00
Vitor Pamplona 4435073234 Merge pull request #2149 from vitorpamplona/claude/group-chat-ui-viewmodel-5WKMV
Add Marmot MLS group messaging UI and integration
2026-04-05 18:43:38 -04:00
Claude 3e49e650c2 feat: read MIP-01 group metadata from MLS GroupContext extensions
Implement end-to-end reading of MarmotGroupData (extension 0xF2EE)
from the MLS GroupContext.extensions and sync to the UI layer.

Quartz (protocol):
- MarmotGroupData.decodeTls(): deserialize from TLS wire format
  (version, nostrGroupId, name, description, admin pubkeys, relays,
  image fields)
- MarmotGroupData.fromExtensions(): find and decode from extension list
- MlsGroup.extensions: expose groupContext.extensions publicly

Commons (shared logic):
- MarmotGroupChatroom: add description, adminPubkeys, relays fields
  as MutableStateFlow for reactive UI
- MarmotManager.groupMetadata(): extract MIP-01 data from group
- MarmotManager.syncMetadataTo(): sync metadata + member count to
  a MarmotGroupChatroom

Sync points (amethyst):
- Account init: sync metadata after restoreAll() for all restored groups
- GiftWrapEventHandler: sync after Welcome processing (group join)
- GroupEventHandler: sync after CommitProcessed (epoch advances may
  update extensions via GroupContextExtensions proposals)

UI (GroupInfoScreen):
- Display group description from MIP-01 metadata
- Display relay URLs from MIP-01 metadata
- Mark admin members with "- admin" suffix (from adminPubkeys)

https://claude.ai/code/session_0194SxKfAU61PY92eqP4cCXM
2026-04-05 22:10:33 +00:00
Claude 0748d2a998 feat: add user search with suggestions to AddMemberScreen
Replace the plain text input with the existing UserSuggestionState +
ShowUserSuggestionList pattern used throughout the app (NewGroupDM,
edit post, etc.).

The flow is now:
1. Type a name, npub, or NIP-05 in the search field
2. Debounced search queries local cache + relays + NIP-05 DNS
3. ShowUserSuggestionList displays matching users with profile
   pictures and display names
4. Tap a user to select them — shows their profile in a selected
   user row with picture, display name, truncated pubkey, and a
   Clear button
5. Tap "Add" to fetch their KeyPackage and complete the invite

https://claude.ai/code/session_0194SxKfAU61PY92eqP4cCXM
2026-04-05 21:51:47 +00:00
Claude 8c2e498a08 feat: complete AddMember KeyPackage fetch and resolve member display names
AddMember flow (was TODO, now functional):
- Account.fetchKeyPackageAndAddMember(): queries outbox relays for the
  target user's KeyPackageEvent (kind:30443) using client.fetchFirst(),
  decodes the base64 KeyPackage content, and calls addMarmotGroupMember()
  which publishes the commit then sends the Welcome gift wrap
- AddMemberScreen now calls the real implementation and navigates back
  on success

Member display names:
- MemberRow now uses LoadUser to resolve Nostr pubkeys to User profiles
  from LocalCache, showing bestDisplayName() instead of raw hex
- UserPicture composable shows profile pictures next to member names
- "(you)" indicator for the current user's entry

https://claude.ai/code/session_0194SxKfAU61PY92eqP4cCXM
2026-04-05 21:43:51 +00:00
Claude 3e14022e38 refactor: convert Marmot dialogs to full route screens
Replace AlertDialog-based CreateGroupDialog and AddMemberDialog with
proper full-screen routes that slide up from the bottom, following the
existing app patterns (ChannelMetadataEdit, NewGroupDM, etc.).

New screens:
- CreateGroupScreen: uses CreatingTopBar with close/create buttons,
  replaces CreateGroupDialog
- AddMemberScreen: uses ActionTopBar with close/add buttons,
  replaces AddMemberDialog

New routes:
- Route.CreateMarmotGroup → composableFromBottom
- Route.MarmotGroupAddMember(nostrGroupId) → composableFromBottomArgs

Updated call sites:
- MarmotGroupListScreen: FAB navigates to Route.CreateMarmotGroup
- MarmotGroupChatScreen: add-member icon navigates to
  Route.MarmotGroupAddMember
- MarmotGroupInfoScreen: add-member icon navigates to
  Route.MarmotGroupAddMember

Deleted old files:
- CreateGroupDialog.kt
- AddMemberDialog.kt

https://claude.ai/code/session_0194SxKfAU61PY92eqP4cCXM
2026-04-05 21:22:46 +00:00
Claude ddca55fae6 feat: add Marmot group info screen, member list, and leave group
Based on MIP spec review, add missing UI screens:

MarmotManager additions (commons):
- memberPubkeys(): extract Nostr pubkeys from MLS ratchet tree
  leaf nodes via Credential.Basic identity
- memberCount(): get group member count
- groupEpoch(): expose current MLS epoch
- GroupMemberInfo data class for leaf index + pubkey pairs

Account & AccountViewModel:
- leaveMarmotGroup(): publish SelfRemove proposal and clean up
- marmotGroupMembers(): expose member list to UI

MarmotGroupInfoScreen (new):
- Group metadata header (name, ID, epoch, member count)
- Member list with leaf indices, clickable to view profiles
- "Leave Group" with confirmation dialog
- "Add Member" access from group info

Navigation:
- Route.MarmotGroupInfo added and wired into nav graph
- Chat screen title now clickable to navigate to group info

https://claude.ai/code/session_0194SxKfAU61PY92eqP4cCXM
2026-04-05 21:09:25 +00:00
Vitor Pamplona 458443f156 Fixes typemismatch 2026-04-05 16:45:47 -04:00