- Created AI_CONTEXT.md as central documentation hub for AI assistants
- Added detailed file-level documentation to all major components
- Documented architecture, design decisions, and security considerations
- Added usage examples and integration guidance
- Improved code discoverability with clear component descriptions
Documentation covers:
- BluetoothMeshService: Core networking and mesh protocol
- BitchatProtocol: Application-layer protocol design
- NoiseProtocol: Cryptographic implementation details
- ChatViewModel: Business logic and state management
- IdentityModels: Three-layer identity architecture
- NoiseEncryptionService: High-level encryption API
- SecureIdentityStateManager: Secure persistence layer
- BinaryProtocol: Low-level wire format
This documentation will significantly improve AI understanding of the codebase structure and enable faster, more accurate assistance with development tasks.
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
* Add MARK headers to improve code organization in major files
* Reorganize peer management functions in BluetoothMeshService
- Removed duplicate getCurrentPeerID(for:) function
- Consolidated peer identity functions in Peer Identity Mapping section
- Moved getPeerFingerprint(), getFingerprint(for:), isPeerIDOurs() to proper location
- Moved getCurrentPeerIDForFingerprint() and getCurrentPeerIDs() from Message Sending section
- Moved notifyPeerIDChange() to Peer Management section
* Consolidate peer management functions in BluetoothMeshService
- Moved getCachedPublicKey() and getCachedSigningKey() from Identity Cache Methods to Peer Connection Management
- Moved getPeerNicknames() and getPeerRSSI() to Peer Connection Management section
- Moved getAllConnectedPeerIDs(), notifyPeerListUpdate(), and cleanupStalePeers() to Peer Connection Management
- Removed duplicate function declarations after consolidation
- Improved code organization by grouping all peer-related functions together
* Consolidate message handling functions in ChatViewModel
- Moved handleHandshakeRequest() from floating location to Message Reception section
- Moved trimMessagesIfNeeded() and trimPrivateChatMessagesIfNeeded() to Message Batching section
- Improved code organization by grouping related message handling functions together
- Removed unnecessary comments from trim functions
* Improve ContentView organization with better documentation
- Added descriptive comments for complex inline computations
- Documented message extraction logic for private vs public chats
- Documented peer data computation and sorting logic
- Improved code readability by explaining complex operations inline
- Note: Attempted to extract complex computations into helper functions, but SwiftUI scope limitations made inline documentation a better approach
---------
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
- Added didSet observer to nickname property to trim on every change
- Trim nickname when loading from UserDefaults
- Update validateAndSaveNickname to properly trim
- Trim received nicknames in announce packets
- Add custom init/decoder for NoiseIdentityAnnouncement to ensure trimming
- Trim nicknames when decoding from binary data
- Modified read receipt to use type marker + binary payload pattern
- Added read receipt type marker handling in noise decryption
- Reduces message size and processing overhead
- Ensures consistency between delivery ACK and read receipt implementations
- Clean up connection states and pending messages during peer ID rotation
- Filter out rotated peer IDs in keep-alive timer to prevent validation attempts
- Add session check before sending cover traffic dummy messages
- Disable cover traffic by default (was sending without user knowledge)
- Only send screenshot notifications when session exists
- Add logging to track automatic message triggers
- Fix compilation errors (SecureLogger.privacy -> security)
- Add handshakeRequest packet type (0x25) to notify recipients about queued messages
- Create HandshakeRequest struct with binary encoding for efficient transmission
- Send handshake requests when messages are queued due to missing session
- Display notifications when someone wants to send messages
- Fix verification persistence bug by adding forceSave on app termination
- Update UI to handle optional encryption icons (hide when no handshake attempted)
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
- Add direct delivery for private messages when recipient is connected
- Implement selective relay using 2-3 best RSSI peers as fallback
- Limit TTL to 2 hops for relayed private messages
- Update all private communication types to use targeted delivery:
- Private messages
- Read receipts
- Delivery ACKs
- Protocol ACKs/NACKs
- Handshake messages
- Identity announces (when targeted)
- Session validation pings
- Version ACKs
- Add intelligent relay logic to forward messages only when recipient is reachable
- Fall back to broadcast only as last resort when no direct path available
This reduces network traffic by ~90% for private communications, improves battery life, and enhances privacy by limiting message visibility.
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
* send nonce in packet
* sliding window and 8 byte nonce
* do not process encrypted messages that arent addressed to us, same for nacks
* compiler error: remove comma
* nonce window 4 bytes
* clean up logging
* Remove sequence numbers from protocol
- Remove sequenceNumber field from BitchatPacket struct
- Update BinaryProtocol to not encode/decode sequence numbers (header size reduced from 17 to 13 bytes)
- Replace sequence-based duplicate detection with content-based using packet ID hash
- Update packet ID generation to use SHA256(senderID + timestamp + type + payload prefix)
- Remove all sequence tracking variables and methods
- Simplify duplicate detection to rely on timestamp and content hashing
* Fix connection stability issues
- Increase peer availability check interval from 5 to 15 seconds
- Fix availability logic to not mark connected peers as unavailable
- Add BLE connection keepalive timer (20s) to prevent iOS timeouts
- Fix missing delivery ACKs by passing peripheral context through Noise decryption
- Reduce identity announce frequency from 2 to 10 seconds minimum
- Remove unnecessary identity announces on connection
- Debounce identity cache keychain saves (2 second delay)
- Add message retry notification handler in ChatViewModel
- Fix version negotiation redundancy by checking existing negotiations
- Keep Noise sessions for already-connected peers
* Fix build errors in message retry handler
- Fix reference to 'displayedMessages' - should be 'messages'
- Fix sendMessage call signature to use individual parameters instead of message object
- Both iOS and macOS builds now succeed
* Fix remaining connection stability issues
- Fix duplicate identity announces with content-based deduplication
- Simplify peripheral mapping with cleaner temp ID to peer ID transitions
- Improve graceful leave detection across peer ID rotations
- Track previousPeerID from announcements to maintain state
- Add time-based cleanup for gracefully left peers
* Fix connection stability issues
- Add special duplicate detection for identity announces
- Simplify peripheral mapping with dedicated structure
- Improve graceful leave detection with peer ID rotation handling
- Track graceful leave timestamps for cleanup
- Transfer states properly during peer ID rotation
* Improve BLE connection stability and message reliability
- Increase peer availability timeout from 5s to 15s to prevent flapping
- Add BLE keepalive timer with 30s interval to maintain connections
- Fix missing delivery ACKs by passing peripheral context through decryption
- Reduce identity announce frequency from 2s to 10s minimum interval
- Add keychain save debouncing with 2s delay to prevent excessive writes
- Implement message retry system for failed deliveries to favorites
- Fix version negotiation redundancy by checking existing state
- Add special duplicate detection for identity announcements
- Implement graceful leave detection with peer ID rotation support
- Simplify peripheral mapping to reduce complexity
- Fix switch statement structure issues causing build errors
These changes significantly improve connection stability, eliminate peer availability flapping, and ensure reliable message delivery.
---------
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
* Add comprehensive RSSI debugging logs
- Log RSSI capture during discovery phase
- Log RSSI reading after peripheral connection
- Log didReadRSSI results including validation and retries
- Log getPeerRSSI() calls and dictionary contents
- Log RSSI transfer from temp IDs to real peer IDs
- Add UI logging to trace nil RSSI values in ContentView
- Track RSSI flow from Bluetooth discovery to UI display
* Add detailed logging for RSSI transfer from temp ID to real peer ID
- Log peripheral mapping updates during announce packet handling
- Track connectedPeripherals state before and after mapping
- Log RSSI transfer from peripheralRSSI to peerRSSI
- Identify whether temp ID is found and properly transferred
* Add peripheral lookup fallback for announce packets
- Log whether peripheral is present when announce received
- Add fallback to look up peripheral if not passed as parameter
- This handles cases where announce is received via relay
* Add comprehensive state logging to getPeerRSSI
- Log connectedPeripherals mapping state
- Log peripheralRSSI dictionary contents
- Log UI-side RSSI lookup attempts with dictionary state
- Track exactly what's in the RSSI lookup tables
* Log peer list shown in UI
* Ensure RSSI transfers even when no temp ID mapping exists
* Add debugging for announce packets without peripheral reference
* Fix build errors and add type annotations
* Fix RSSI mapping for relayed announce packets
- Add fallback logic to match unmapped peripherals with announced peers
- Transfer RSSI from temp UUID to real peer ID when single unmapped peripheral exists
- Implement periodic RSSI updates every 10 seconds for all connected peripherals
- Improve RSSI debugging logs to track mapping state
* Fix RSSI mapping condition for single unmapped peripheral
- Remove peerNicknames.count == 0 condition that was preventing mapping
- Map single unmapped peripheral to announcing peer regardless of nickname state
- Remove temp RSSI entries when transferring to real peer ID
- Improve logging to show successful RSSI transfers
* Improve getPeerRSSI to skip temp IDs and check known peers
- Skip temp IDs (non-16 character) when iterating connectedPeripherals
- Add fallback to check peerNicknames for known peers without peripherals
- Check both peerRSSI and peripheralRSSI for known peers
- Improve RSSI lookup coverage for edge cases
* Remove RSSI debug logging and fix build warnings
- Remove all RSSI-related debug logging added during troubleshooting
- Keep functional RSSI tracking code intact
- Fix unused variable warnings in didReadRSSI and updateAllPeripheralRSSI
- Clean up verbose logging while maintaining core functionality
---------
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
- Removed COMMANDS section from AppInfoView
- Added WARNING section about unaudited private message security
- Warning displayed at bottom with red styling for visibility
- Users advised not to use for critical situations until audit complete
- Added 0.1s delay before focusing text field on appear
- This gives iOS time to properly layout keyboard views
- Prevents constraint conflict warnings in system keyboard
- Added gracefullyLeftPeers tracking to prevent duplicate disconnect messages
- Show disconnect message immediately when leave announcement is received
- Skip duplicate message when physical disconnect happens after graceful leave
- Fixed API misuse by adding peripheral.state checks before readRSSI() calls
- Added debug logging to track graceful leave flow
- Track peers that gracefully left with 'gracefullyLeftPeers' set
- Only log disconnect message if peer didn't send leave message first
- Add state checks before all peripheral.readRSSI() calls
- Prevents API misuse errors for disconnected peripherals
- Clear gracefullyLeftPeers after 5 seconds to handle race conditions
- Disable iOS autocorrection on text fields to prevent conflicts
- Add NaN validation for all geometry and gesture calculations
- Fix frame calculations to handle invalid geometry values
- Validate translation and velocity values in drag gestures
- Prevent Result accumulator timeout warnings
- Add LazyLinkPreviewView wrapper to defer link preview loading
- Only render sidebar content when visible or animating
- Defer expensive computations until components are shown
- Reduces initial render cost and memory usage
- Remove unnecessary Array() conversions in messages ForEach
- Optimize URL ForEach to use indices instead of enumerated
- Simplify autocomplete ForEach by removing unneeded enumeration
- Pre-compute all peer display data outside ForEach for sidebar
- Create PeerDisplayData struct to bundle peer properties
- Move sorting and data preparation outside the render loop
- Add 150ms debounce to text field onChange handler
- Prevents excessive autocomplete calculations during rapid typing
- Add timer cleanup in onDisappear
- Works for both main chat and private chat inputs
- Increased vertical padding from 1px to 2px per message
- Total spacing between messages now 4px (was 2px)
- Improves readability and visual separation
- Removed redundant animation modifiers (multiple animations on same view)
- Replaced spring animations with simpler easeInOut/easeOut curves
- Spring animations are computationally expensive, now using 0.2s easeInOut
- Added scroll throttling to prevent excessive animations on message updates
- Scroll animations limited to once per 0.5 seconds
- Removed withAnimation wrapper from scrollTo calls
- Simplified drag gesture animations from spring to easeOut
This reduces CPU usage during UI transitions and message updates
- Added message batching system with 100ms window
- Created pendingMessages array for public messages
- Created pendingPrivateMessages dictionary for private messages
- Added scheduleBatchFlush() to consolidate updates
- Batch all incoming messages from didReceiveMessage
- Batch system messages (connect/disconnect/screenshot)
- Keep immediate updates for user's own sent messages
- Single UI update per batch instead of per message
- Flush pending messages on app background/terminate
- Clear timer on deinit
This reduces UI updates when multiple messages arrive quickly
- Added font weight logic to formatMessageAsText and formatMessage
- User's own @nickname appears bold (weight: .bold)
- Other nicknames remain medium weight
- Helps visually distinguish own messages from others
- Simplified getSenderColor to always return primary color
- Removed RSSI color calculation logic from formatMessageAsText
- Removed RSSI color calculation logic from formatMessage
- All sender names now use consistent green color
- RSSI information remains visible only in peer list
- Cache getRSSIColor results with key format: "\(rssi)_\(isDark)"
- Cache getEncryptionStatus results with peerID as key
- Add cache invalidation methods for both caches
- Invalidate encryption cache when:
- Encryption status is updated
- Fingerprints are verified
- Peer authentication callbacks trigger
- Invalidate RSSI cache when peer list updates
- Clear all caches in panicClearAllData
This reduces redundant calculations during view updates and improves performance
- Add URL detection to message formatting with blue color and underline
- Replace List with ScrollView for precise spacing control
- Use minimal vertical padding (1px) between messages
- Remove LazyLinkPreviewView, use LinkPreviewView directly
- URLs now appear highlighted in message text AND show preview below
- Reduce VStack spacing from 4 to 2 and nested VStack from 2 to 0
- Set list row insets top/bottom to 0 to minimize spacing on iPhone
- Remove all markdown link parsing and formatting
- Share plain URLs instead of markdown when using share extension
- Keep only plain text URL detection and preview functionality
- Convert BitchatMessage from struct to class for efficient caching
- Cache formatted AttributedStrings to avoid expensive regex on every render
- Replace ScrollView+LazyVStack with native List for better cell reuse
- Implement message windowing (show last 100 messages for performance)
- Add LazyLinkPreviewView that defers loading for 0.5s to improve scroll performance
These optimizations significantly improve scroll performance, especially with large message lists.
- Validate nickname only when field loses focus or on submit
- Replace empty nicknames with anon+random 4 digits (e.g. anon3847)
- Remove auto-save timer to prevent validation while typing
- Add FocusState to detect when user exits the field
- Don't show PM notifications when the private chat is already open
- Store peer ID in notification userInfo for reliable chat opening
- Tap notification to open the correct private chat using peer ID
- Check both in ChatViewModel (when receiving) and NotificationDelegate (when presenting)
- Tap any message to show action sheet with user options
- Actions include: private message, hug, slap, and block
- Only appears for messages from other users (not system or self)
- Integrates with existing chat commands (/hug, /slap, /block)
- Make entire peer list row tappable for starting private chats
- Fix separator bar visibility when private chat is fully open (offset by -1px)
- Keep favorite star as separate tap target
- Preserve double-tap gesture for showing fingerprints