Commit Graph

9961 Commits

Author SHA1 Message Date
Vitor Pamplona 29db4ca0e3 Merge pull request #1825 from vitorpamplona/claude/event-sync-screen-sYGtN
Add Event Sync feature to redistribute events across relays
2026-03-19 09:54:26 -04:00
Vitor Pamplona 78ffb9fce4 Merge branch 'main' into claude/event-sync-screen-sYGtN 2026-03-19 09:54:20 -04:00
Vitor Pamplona 30f862cf26 Increase max parallel to 50 2026-03-19 09:50:50 -04:00
Vitor Pamplona ab81b2a71d Improving calendar debug 2026-03-19 09:50:31 -04:00
Vitor Pamplona ec29a47dc4 More debugging information 2026-03-19 09:34:52 -04:00
Vitor Pamplona 98578de840 Merge pull request #1874 from vitorpamplona/l10n_crowdin_translations
New Crowdin Translations
2026-03-19 08:51:23 -04:00
Crowdin Bot 311bbe19cf New Crowdin translations by GitHub Action 2026-03-19 12:45:49 +00:00
Vitor Pamplona 3f841c94ec Merge pull request #1873 from nrobi144/feat/desktop-media
feat(desktop): Full media parity — images, video, audio, encrypted DMs, upload, lightbox
2026-03-19 08:44:21 -04:00
nrobi144 5b2f2ca42b feat(chats): per-message encryption badge — lock for NIP-17, lock-open for NIP-04
Show a small lock icon next to the timestamp on each DM message:
- NIP-17 (ChatMessageEvent, ChatMessageEncryptedFileHeaderEvent): filled
  lock in primary color — relay can't see sender/recipient
- NIP-04 (PrivateDmEvent): open lock in muted gray — legacy encryption,
  metadata visible to relays

Matches Android's IncognitoBadge pattern. Both NIP-04 and NIP-17 messages
in the same 1-on-1 conversation produce identical ChatroomKeys, so they
merge into one conversation — the badge is the only way to tell them apart.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:23:06 +02:00
nrobi144 f3e55f9958 fix(chats): handle ChatMessageEncryptedFileHeaderEvent in GiftWrap unwrap
The GiftWrap inner event handler only processed ChatMessageEvent (kind 14)
and ReactionEvent. ChatMessageEncryptedFileHeaderEvent (kind 15) was
silently dropped, so encrypted file attachments never appeared in DMs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:11:46 +02:00
nrobi144 35b58e489b feat(chats): right-click context menu on encrypted files — download + forward
Right-click on encrypted file attachments in DMs now shows a context menu:
- "Save to disk" — decrypts and saves via native file dialog
- "Forward" — placeholder callback for forwarding to another conversation

Also caches decrypted bytes (not just image bitmap) so save doesn't
re-download. Non-image files also get decrypted on load for save support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:06:26 +02:00
nrobi144 d9848b868b feat(chats): always show attach button, auto-force NIP-17 with snackbar
- Attach button always visible in DM input (not gated on NIP-17 mode)
- Drag-and-drop always enabled
- When files are attached in NIP-04 mode, auto-switches to NIP-17
  with snackbar: "Switched to NIP-17 — file attachments require
  encrypted messaging"
- NIP-17 toggle remains for manual control

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:02:05 +02:00
nrobi144 9187bf448f fix(chats): pass compactMode through RootContent — single-pane keeps split
compactMode was hardcoded in the Messages branch of RootContent, which is
shared between deck and single-pane. Now compactMode is a RootContent
parameter: deck passes true, single-pane defaults to false.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 07:53:03 +02:00
nrobi144 0184ebad11 fix(test): disambiguate mock upload call after ByteArray overload
The new ByteArray upload overload on DesktopBlossomClient made the
positional any() mock call ambiguous. Specify explicit type parameters.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 07:51:22 +02:00
nrobi144 e06287acb3 feat(chats): stacked messages layout in deck columns
In multi-deck mode, Messages column now uses stacked navigation instead
of side-by-side split pane. Full-width contact list OR full-width chat —
clicking a conversation navigates to chat, back arrow returns to list.

Single-pane mode keeps the existing split layout (280dp list + flex chat).

Changes:
- Add compactMode param to DesktopMessagesScreen (default false)
- Extract SplitMessagesContent and CompactMessagesContent composables
- Add onBack callback to ChatPane with back arrow in header
- Remove hardcoded 280dp from ConversationListPane (caller controls width)
- Pass compactMode=true from deck RootContent

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 07:49:36 +02:00
nrobi144 598256639b fix(chats): share single DesktopIAccount across deck — DMs now visible
DeckColumnContainer was creating its own DesktopIAccount (and ChatroomList)
for the Messages column, while Main.kt created a separate one for DM relay
subscriptions. Events were added to one ChatroomList but the UI read from
the other, so DMs never appeared.

Fix: thread the single iAccount from Main.kt through DeckLayout →
DeckColumnContainer → RootContent → DesktopMessagesScreen. Removed the
duplicate DesktopIAccount and DmSendTracker creation from RootContent.

Audited all other deck column types — no similar instance duplication found.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 07:31:27 +02:00
nrobi144 24d4073b9b feat(media): encrypted file sharing in desktop DMs (NIP-17 Phase 6)
Add full send + receive encrypted media support in desktop DM chat:
- Paperclip attach button and drag-and-drop in ChatPane (NIP-17 mode only)
- AES-GCM encryption before upload to Blossom server
- ChatMessageEncryptedFileHeaderEvent (kind 15) wrapped in GiftWrap
- sendNip17EncryptedFile() added to IAccount interface and implementations
- DesktopUploadOrchestrator.uploadEncrypted() with proper encrypted hash
- DesktopBlossomClient ByteArray upload overload for encrypted blobs
- LRU cache in EncryptedMediaService to avoid re-downloading
- Error handling: retry on failure, disable send during upload

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 06:53:36 +02:00
Vitor Pamplona 3e3adaff10 Finalizes the RelaySync utility 2026-03-18 17:35:05 -04:00
Vitor Pamplona e57023cad9 Fix: Filters onCannotConnect to the relays that sent a req 2026-03-18 17:34:50 -04:00
davotoula 7bfc35e04d Fixes Applied
Code reuse
  - Extracted remuxTracks() helper to deduplicate video/audio remux loop (~40 lines)
  - Extracted stripAfterCompression() to deduplicate identical blocks in upload()/uploadEncrypted()
  - Replaced 8 identical showStrippingFailureDialog() copy-pastes with shared SuspendableConfirmation utility
  Privacy
  - 4 metadata ViewModels now error on strip failure instead of silently uploading unstripped media
  Efficiency
  - Eliminated temp input file copy for video/audio — MediaExtractor reads URIs directly
  Bug fixes
  - Fixed Long.toInt() overflow for MP3 files >2GB
  - Fixed MP3 temp file leak on exception and null InputStream paths
  Cleanup
  - Mutex field and wrapping the suspendCancellableCoroutine in mutex.withLock. Concurrent callers now queued
  - Converted MetadataStripper from class to object (stateless)
  - Moved StrippingFailureState from service layer to UI as generic ConfirmationCallbacks
2026-03-18 20:59:46 +01:00
davotoula 0cf256e5b2 Merge branch 'main-upstream' into claude/strip-file-metadata-sVIEd 2026-03-18 19:32:43 +01:00
davotoula bfc04497d6 Profile picture upload fails with an error instead of silently uploading unstripped media when stripping fails 2026-03-18 19:25:57 +01:00
davotoula eb13bab738 fix grammar 2026-03-18 18:31:34 +01:00
davotoula 97e6206244 fix persisted account preference 2026-03-18 18:31:07 +01:00
davotoula a7ac30493c Extension mismatch fix
Temp file leak fix
2026-03-18 18:25:31 +01:00
davotoula 49c8423be5 moving the stripping decision after compressIfNeeded 2026-03-18 18:20:01 +01:00
davotoula 127079ede3 - Hide privacy toggle when video compression is selected (compression
already handles metadata stripping)
- Pass stripMetadata=false when toggle is hidden for compressed video
- Hide compression quality for audio and other non-compressible media types
- refactor
2026-03-18 13:54:15 +01:00
nrobi144 c90bf8f610 feat(media): add Note/Picture post type selector; fix gallery crash
- Post type toggle (Note vs Picture/kind 20) in compose dialog, only
  shown when image files are attached. Text input disabled in picture mode.
- Fix LazyVerticalGrid crash in GalleryTab: bounded height via
  fillParentMaxHeight() when nested inside LazyColumn.
- Phase 1 testing plan: all pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 14:42:44 +02:00
nrobi144 cf17dea53f feat(media): add Note/Picture post type selector in compose dialog
When images are attached, a Note/Picture toggle appears letting the user
publish as kind 20 (PictureEvent) instead of kind 1. Text input is
disabled in picture mode. Selector only shows for image file types.
Updates testing plan: Phase 1 all pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 14:37:48 +02:00
nrobi144 1d1d32da0e feat(media): add server selector to compose dialog; update testing plan
Server selector dropdown appears when files are attached, letting the
user choose which Blossom server to upload to. Updates testing plan:
Phase 2 & 3 all pass, Phase 9 audio tested with volume bug tracked.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 14:26:47 +02:00
nrobi144 836e024bd7 feat(media): use VLC :start-volume for initial audio; document volume bug
Passes :start-volume media option to VLC on play. Removes polling/delay
volume hacks. Documents 9.7 volume bug in testing plan — VLC ignores
initial volume on macOS, needs further investigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:26:52 +02:00
nrobi144 f0c80f3c7c fix(media): delay volume enforcement — VLC audio output not ready at playing event
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:34:36 +02:00
nrobi144 11b9fdad80 fix(media): enforce volume on playback start — VLC resets volume on new media
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:30:57 +02:00
nrobi144 2a6087af27 feat(media): global media player — persistent playback across navigation
Media playback now survives navigation. A GlobalMediaPlayer singleton owns
VLC players and exposes StateFlows. Composables are thin viewports.
NowPlayingBar has full controls (volume, mute, save, fullscreen).
GlobalFullscreenOverlay renders video fullscreen above all screens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:27:13 +02:00
davotoula 20ab105e44 feat: add metadata stripping failure dialog to all upload ViewModels
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 11:12:36 +01:00
davotoula c0632e17bd feat: add onStrippingFailed callback to upload orchestrators
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:51:30 +01:00
davotoula 9ce1ff3e63 feat: plumb stripMetadata from UI through ViewModels to upload orchestrators
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:50:16 +01:00
davotoula 3b1b15911f feat: rename stripLocationMetadata to stripMetadata in UI state and dialogs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:42:59 +01:00
davotoula c76459859d feat: update all Screen call-sites for new stripMetadata onAdd parameter
Add 6th Boolean parameter to onAdd lambdas in all 6 files that call
ImageVideoDescription. The parameter is unused (_) for now in 5 sites
and named in ShortNotePostScreen for future plumbing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:38:04 +01:00
davotoula 0d514a46d7 feat: add privacy toggle to ImageVideoDescription
Add stripMetadata state and SettingSwitchItem toggle. Extend onAdd
callback signature with 6th Boolean parameter for stripMetadata.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:36:56 +01:00
davotoula f7a9389a66 feat: add string resources for privacy toggle and metadata dialog
Rename strip_location_metadata_label/description to strip_metadata_label/description
to reflect broader scope. Add new strings for the metadata stripping failure dialog.
Update references in NewMediaView.kt and ChatFileUploadDialog.kt.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:36:03 +01:00
davotoula 24e8487db6 fix: hide codec toggle when video compression is set to uncompressed
When the compression quality slider is set to UNCOMPRESSED (value 3),
no encoding happens so the H264/H265 codec choice is irrelevant. Hide
the codec toggle in this case to avoid confusion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:33:35 +01:00
davotoula 0e62904883 fix: hide compression slider for audio uploads
Audio has no compression support in MediaCompressor (falls through to
no-op), so showing the compression quality slider for audio files is
misleading. This removes audio from the slider visibility condition in
ImageVideoDescription and wraps the unconditionally-shown slider in
ChatFileUploadDialog with a media type check.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:33:28 +01:00
davotoula 489e731eea feat: add MP3 ID3 tag stripping and early-exit for unsupported audio
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:29:09 +01:00
davotoula b9d62edaad feat: support multiple tracks in audio metadata stripping
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:28:13 +01:00
davotoula 7219c787a6 fix: update direct MetadataStripper.strip() call sites for StrippingResult
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:26:02 +01:00
davotoula 4fc5166815 feat: propagate StrippingResult through UploadOrchestrator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:25:55 +01:00
davotoula f9176fc3fb feat: add StrippingResult data class to MetadataStripper
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:25:50 +01:00
nrobi144 6e1315a4fa feat(media): improve video player pool, thumbnail extraction, and NoteCard layout
Harden VLC player pool with dedicated thumbnail acquisition, better error
logging, and defensive buffer checks. Simplify lightbox/video controls,
fix NoteCard media sizing across feed, thread, bookmarks, and search screens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 09:24:00 +02:00
Vitor Pamplona f25be5e7bd removes the benchmark action... it's not that useful. 2026-03-17 16:00:46 -04:00