Commit Graph
660 Commits
Author SHA1 Message Date
jackandislam c52a2a7772 Ensure /clear and panic triple-tap delete media files
Fix: /clear command and panicClearAllData() now properly delete media files

1. /clear (triple-tap on chat):
   - Deletes outgoing media (voice notes, images, files)
   - Conservative: only our sent media, preserves received media
   - Runs in background to avoid UI freeze

2. panicClearAllData() (triple-tap on bitchat/ header):
   - Deletes ALL media files (incoming + outgoing)
   - Removes entire files directory and recreates structure
   - Ensures complete data wipe for emergency scenarios

Both operations run async on .utility queue to prevent blocking UI.
2025-10-15 17:37:19 +01:00
jackandislam 3df0aa0cc4 Make voice note loading completely lazy with deferred initialization
Aggressive performance optimization to prevent UI freezes:

Problem: Even with async loading, creating 10+ VoiceNotePlaybackController
instances simultaneously (when scrolling past multiple voice notes) spawned
20+ concurrent background tasks, potentially starving main thread.

Solution - Ultra-lazy loading:
1. VoiceNotePlaybackController.init() now does ZERO work
   - No duration loading
   - No player creation
   - Instant initialization

2. Duration loaded on-demand via public loadDuration() method
   - Called from VoiceNoteView.onAppear after 150ms delay
   - Reduced priority: .utility instead of .userInitiated
   - Guard prevents duplicate loading

3. Waveform loading also deferred 150ms
   - Gives UI time to settle after message appears
   - Prevents task storms when multiple voice notes appear

This spreads the work over time instead of all at once.
2025-10-15 17:37:19 +01:00
jackandislam 46caded099 Cache geohash identity in ChatViewModel to prevent crypto during rendering
Additional optimization for location channels (voice notes are mesh-only,
but this helps with text message rendering in geohash channels):

- Add cachedGeohashIdentity to avoid deriveIdentity calls during rendering
- Check cache before falling back to crypto derivation
- Reduces main thread crypto work in location channels
2025-10-15 17:37:19 +01:00
jackandislam a04ac9dabd Cache Nostr identity derivation to prevent crypto during view rendering
Critical performance fix:

Problem: formatMessageHeader() called deriveIdentity(forGeohash:) during
every SwiftUI render for every media message. Each call performed:
- Keychain I/O (getOrCreateDeviceSeed)
- HMAC-SHA256 computation
- Up to 10 secp256k1 key validations (elliptic curve crypto)

With multiple media messages, this resulted in 100s of milliseconds of
blocking crypto on main thread per render cycle.

Solution: Add thread-safe cache for derived identities
- Check cache before expensive crypto operations
- NSLock protects concurrent access
- Identity is deterministic per geohash, so caching is safe

This eliminates crypto from the hot rendering path.
2025-10-15 17:37:19 +01:00
jackandislam 1825d115bc Eliminate disk I/O from SwiftUI view rendering path
Critical performance fix for UI freezes when receiving media:

Problem: mediaAttachment(for:) was called during every SwiftUI render,
performing synchronous disk I/O on main thread:
- FileManager.fileExists() called 2-6x per message (checking subdirs)
- applicationFilesDirectory() creating directories on every call
- With multiple media messages, this meant 20-100+ disk ops per render

Solution:
1. Remove fileExists checks - construct URLs directly
   - Files are validated during playback/display (fail gracefully if missing)
   - Sender determines subdirectory (outgoing vs incoming)

2. Cache applicationFilesDirectory() result
   - Static cache prevents repeated FileManager.url() calls
   - Directory created only once

3. Remove redundant playback.replaceURL() in VoiceNoteView.onAppear
   - Controller already initialized with correct URL

This eliminates ALL disk I/O from the view rendering hot path.
2025-10-15 17:37:19 +01:00
jackandislam 9754881af8 Fix memory leaks and post-playback freeze
Fixes:
1. Post-playback freeze: audioPlayerDidFinishPlaying now dispatches to main
   thread before updating @Published properties (Swift concurrency violation)

2. Unbounded waveform cache: Implement LRU eviction with 20-entry limit
   - Track last access time for each cached waveform
   - Evict oldest entry when cache is full
   - Prevents unlimited memory growth as voice notes accumulate

3. Audio buffer memory leaks: Wrap computeWaveform in autoreleasepool
   - AVAudioPCMBuffer allocations are autoreleased
   - Pool ensures buffers are freed promptly

4. Image processing memory: Add autoreleasepool around compression loops
   - Each jpegData() call creates temporary objects
   - Inner pool per iteration prevents memory spikes during quality search

Memory should now remain stable during extended use.
2025-10-15 17:37:19 +01:00
jackandislam 59cc857fde Fix UI freeze when receiving voice notes
Problem: AVAudioPlayer initialization in VoiceNotePlaybackController.init()
was running synchronously on main thread during view creation, blocking
UI for 50-200ms per voice note.

Solution:
- Remove eager preparePlayer() call from init
- Load duration asynchronously on background queue
- Player is only prepared when playback is actually requested via ensurePlayerReady()

This prevents UI freezes when voice notes appear in the chat.
2025-10-15 17:37:19 +01:00
jackandislam f0ca1b27c2 Fix critical issues from PR #681 review
Critical fixes:
- BinaryProtocol: Return nil for unknown versions (prevents buffer underflows)
- Add BinaryProtocol.Offsets struct to centralize magic numbers
- Replace magic offset calculations with named constants

Security/Privacy:
- FileAttachmentView: Use url.lastPathComponent instead of url.path
  (prevents exposing full system paths)

Documentation:
- Fix compression algorithm documentation (zlib, not LZ4)

All tests passing.
2025-10-15 17:37:19 +01:00
jackandislam 5beff8b4dc Fix binary protocol test fixtures 2025-10-15 17:37:19 +01:00
jackandislam ba49b885bb Reset BLE assembler on stalled fragment trains 2025-10-15 17:37:19 +01:00
jackandislam ac10e906c0 Drop attachment ceilings to 1 MiB and bump release version 2025-10-15 17:37:19 +01:00
jackandislam 119e882574 Guard peer map reads on BLE message path 2025-10-15 17:37:19 +01:00
jackandislam 0acbbdf2e3 Restore BLE broadcasts when notify buffer is saturated 2025-10-15 17:37:19 +01:00
jackandislam 40fe0c8ba5 Fix cleanupLocalFile lookup 2025-10-15 17:37:19 +01:00
jackandislam 7593053137 Resolve image/voice path handling 2025-10-15 17:37:19 +01:00
jackandislam 4dde063027 Hide absolute paths in media messages 2025-10-15 17:37:19 +01:00
jackandislam 8c4fead945 Stub file transfer methods in mock 2025-10-15 17:37:19 +01:00
jackandislam 2543277755 Stub file transfer methods in mock 2025-10-15 17:37:19 +01:00
jackandislam a8ce4cbf64 Use unique transfer identifiers 2025-10-15 17:37:19 +01:00
jackandislam 93aa714ed4 Preserve packet version when signing 2025-10-15 17:37:19 +01:00
jackandislam 9c7bf26e13 Fix CFMutableData handling 2025-10-15 17:37:19 +01:00
jackandislam c29c7d83fe Target image byte size across platforms 2025-10-15 17:37:19 +01:00
jackandislam 7f743d48fe Normalize mac JPEG color space 2025-10-15 17:37:19 +01:00
jackandislam 27c39332d5 Strip metadata in mac image encoding 2025-10-15 17:37:19 +01:00
jackandislam 53c08d6807 Revert unsupported JPEG option 2025-10-15 17:37:19 +01:00
jackandislam 7efe0a23b1 Align mac image JPEG encoding 2025-10-15 17:37:19 +01:00
jackandislam 8dedc81512 Allow user-selected write access 2025-10-15 17:37:19 +01:00
jackandislam 5cbe9d4aa7 Fix image attachment detection 2025-10-15 17:37:19 +01:00
jackandislam 515fae9e25 Use save panel for mac image export 2025-10-15 17:37:19 +01:00
jackandislam 0946d3921f Keep processed images for outgoing messages 2025-10-15 17:37:19 +01:00
jackandislam 1d40950118 Lowercase image preview buttons 2025-10-15 17:37:19 +01:00
jackandislam b404d48ba6 Reblur images via swipe 2025-10-15 17:37:19 +01:00
jackandislam 2f1ba27d51 Allow long-press reblur on images 2025-10-15 17:37:19 +01:00
jackandislam 23124b36b7 Use Photos picker on mac 2025-10-15 17:37:19 +01:00
jackandislam 3e8d05fa2e Restore mac photo picker access 2025-10-15 17:37:19 +01:00
jackandislam c36b582209 Display recording milliseconds 2025-10-15 17:37:19 +01:00
jackandislam 3c66ca7499 Harden attachment transfer bookkeeping 2025-10-15 17:37:19 +01:00
jackandislam a042576652 Describe microphone usage 2025-10-15 17:37:19 +01:00
jackandislam 3c120042a4 Permit mac media library access 2025-10-15 17:37:19 +01:00
jackandislam 4e3603d5e4 Allow mac microphone access 2025-10-15 17:37:19 +01:00
jackandislam f7ad970a83 Enable mac attachment importers 2025-10-15 17:37:19 +01:00
jackandislam 4cc87633e1 Fix compressed BLE file transfers 2025-10-15 17:37:19 +01:00
jackandislam 2d565ad918 Stop dropping partial BLE frames while assembling notifications 2025-10-15 17:37:19 +01:00
jackandislam b4cb4d36f1 Log incomplete BLE frames for debugging 2025-10-15 17:37:19 +01:00
jackandislam 7fcef2a9cb Add detailed logging for BLE fragment assembly 2025-10-15 17:37:18 +01:00
jackandislam e7dc0e0c5a Let BLE assembler accept large frames up to hard cap 2025-10-15 17:37:18 +01:00
jackandislam 3b2c7d2f73 Add guard to drop oversized BLE notification assemblies 2025-10-15 17:37:18 +01:00
jackandislam 209f926990 Revert "Raise BLE notification buffer cap for large file transfers"
This reverts commit b624523af843475db84e4a846db8dcbe824ae408.
2025-10-15 17:37:18 +01:00
jackandislam ef8b509ea5 Raise BLE notification buffer cap for large file transfers 2025-10-15 17:37:18 +01:00
jackandislam 06b5bdb6da Allow file transfers from connected but unverified peers 2025-10-15 17:37:18 +01:00