Critical fixes:
1. Match messages by sender nickname in addition to peer ID (since peer IDs change)
2. Send read receipts to CURRENT peer ID, not old senderPeerID from message
3. Remove requirement for senderPeerID to be non-nil (blocks older messages)
4. Add extensive logging to trace the flow
The core issue was that peer IDs are ephemeral and change between sessions:
- Rick sends message with peer ID A
- Later, Jack connects to Rick who now has peer ID B
- Read receipt needs to be sent to B, not A
- Messages need to be matched by nickname, not just peer ID
- Added logic to prevent downgrading from 'read' status to 'delivered'
- When an ACK arrives after a read receipt, the read status is preserved
- This fixes the issue where blue checkmarks briefly appear then revert to green
- Applied fix to all message types (main, private, room)
- Added app activation observer to send read receipts when app becomes active
- Send read receipts for all unread messages when receiving a new message while chat is open
- Added import for NSApplication/UIApplication notifications
- This ensures messages are marked as read even when opening chat from notifications or returning to app
- Added delay to ensure messages are loaded before checking
- Fixed logic to check if message is FROM the other person (not TO them)
- Added onAppear handler to send read receipts when view loads
- Added detailed logging to debug the flow
- Now correctly identifies received messages that need read receipts
- Changed back to bold blue double checkmarks for read status
- Send read receipts for both 'sent' and 'delivered' status messages
- Added onChange handler to send read receipts whenever switching to a private chat
- Made markPrivateMessagesAsRead public so it can be called from views
- This ensures read receipts are sent when opening a chat from notifications or any other way
- Changed from double checkmarks to checkmark.circle.fill icon
- Made the icon larger (size 12) and bold
- Used explicit RGB blue color (0.0, 0.478, 1.0)
- This should make it very obvious when a message has been read
- Read receipts were being sent to the current ephemeral peer ID instead of the message's senderPeerID
- This caused read receipts to be lost when peer IDs changed between sessions
- Now using message.senderPeerID consistently for all read receipt sending
- Added detailed logging to track which peer ID receives the read receipt
- Add logging to track what delivery status is shown in UI
- Add logging when green/blue checkmarks appear
- Force complete dictionary reassignment to trigger SwiftUI updates
- Add diagnostics to understand why blue checkmarks aren't showing
- Use message ID instead of index for ForEach to trigger proper updates
- Add explicit objectWillChange.send() when updating delivery status
- Fix scroll-to-bottom logic to use message IDs
- This should make blue checkmarks appear when read receipts are received
- Add detailed logging to track read receipt generation
- Handle messages that don't have delivery status (older messages)
- Send read receipts for all unread messages when opening chat
- Fixed BinaryProtocol to actually read and use the message ID
- Pass the decoded ID to BitchatMessage constructor
- This ensures ACKs reference the correct original message ID
- Track message IDs through the delivery process
- Log ACK generation and processing
- Log status updates in ChatViewModel
- Log read receipt generation and sending
- Added ReadReceipt structure and .readReceipt message type
- Added .read delivery status with blue checkmarks in UI
- Send read receipts when viewing a private chat
- Send read receipts immediately for new messages if chat is open
- Update message status from delivered to read when receipt received
- Fixed nested lock acquisition in trackMessage/scheduleTimeout
- Properly handle lock release before calling methods that need locks
- Ensure retryDelivery and handleTimeout don't cause deadlocks
- Release locks before calling external methods
- Pass message ID from ChatViewModel to BluetoothMeshService
- Preserve original message ID when creating ACK messages
- Move delivery tracking to ChatViewModel for consistent IDs
- Update project.yml to match current project structure
The crash was caused by concurrent access to CryptoKit signing operations
from multiple threads. Added thread-safe access using a concurrent queue
with barriers for write operations and sync reads.
This fixes the EXC_BAD_ACCESS crash seen in TestFlight build.
- Explains no data collection, no servers, no tracking
- Documents local-only storage including identity key for favorites
- Details encryption methods and user rights
- Emphasizes privacy-first philosophy
- Written in plain language for accessibility
- Add performance features to README.md including LZ4 compression, battery optimization, and network efficiency
- Add comprehensive Performance Optimizations section to WHITEPAPER.md with technical diagrams
- Update architecture diagram to include Compression Service and Battery Optimizer
- Document future performance enhancements including WiFi Direct transport
- Delete LoggingService.swift
- Remove all bitchatLog() function calls throughout the codebase
- Update Xcode project to remove LoggingService references
- Clean up debug logging statements from all services and views
- Add LZ4 message compression for 30-70% bandwidth reduction
- Implement adaptive battery optimization with power modes
- Optimize Bloom filter with bit-packed storage and SHA256 hashing
- Create WiFi Direct integration plan for future implementation
- Enable and update Bloom filter tests
- Delete LoggingService.swift
- Remove all bitchatLog() function calls throughout the codebase
- Update Xcode project to remove LoggingService references
- Clean up debug logging statements from all services and views
- Add LZ4 message compression for 30-70% bandwidth reduction
- Implement adaptive battery optimization with power modes
- Optimize Bloom filter with bit-packed storage and SHA256 hashing
- Create WiFi Direct integration plan for future implementation
- Enable and update Bloom filter tests
- Implement room-wide message retention controlled by room owners
- Change username format from <name> to <@name> throughout UI
- Fix text alignment in chat messages (consistent font sizes)
- Add comprehensive technical whitepaper with Mermaid diagrams
- Update README with current features and commands
- Add retention status indicators and announcements
- Update command help text to use short versions (/j, /m)
- Load saved messages for saved rooms during app initialization
- Messages are now restored when reopening the app
- Rooms marked as saved will show their message history immediately
- Add bookmark icon button in room header to toggle save status
- Use bookmark.fill when room is saved, bookmark when not
- Button shows yellow when saved, default color when not
- Integrate with existing /save command functionality
- Add savedRooms published property for reactive UI updates
- Replace /list with /rooms showing all discovered rooms with join status
- Remove /discover command (merged into /rooms)
- Rename /favorite to /save for clarity
- Make room-specific commands (/transfer, /pass, /save) only appear in room context
- Remove voice notes from app info (feature doesn't exist)
- Remove Commands line from app info screen
- Show checkmark (✓) for joined rooms in /rooms output
- Add KeychainManager for secure password storage
- Implement MessageRetentionService for encrypted local storage of favorite room messages
- Add MessageRetryService for automatic retry of failed messages
- Add /favorite command to toggle room retention
- Add /discover command to find active rooms
- Fix all force unwrapped optionals in BluetoothMeshService
- Update app info screen with new features
- Integrate all services with proper cleanup on panic
- Add key commitment scheme for immediate password verification
- Implement ownership transfer with /transfer command
- Add password change functionality with /pass command
- Include room metadata in initialization messages
- Remove /help command and rename /changepass to /pass
- Make room names tappable to show sidebar
- Remove spaces in person/room counter display
- Update UI to show lock icons and orange colors for protected rooms
- Fix password verification to work with empty rooms
- Add comprehensive tests for new functionality
This update significantly improves the security and usability of
password-protected rooms by allowing immediate verification without
waiting for encrypted messages.
- Add lock icon to room header for password management
- Change "leave" to "leave room" for clarity
- Fix bug where non-members appeared in room member list
- Only process room messages if user has joined the room
- Initialize room data structures on app launch
- Prevent auto-join when just mentioning a room
- Room creators can set/remove passwords for their rooms
- Passwords are used to derive encryption keys via PBKDF2
- All messages in password-protected rooms are encrypted with AES-GCM
- Room protection status is announced to all peers
- Password and room data persists across app launches
- Visual lock indicators for password-protected rooms
- Password prompts when joining protected rooms
- Only room creators can modify password settings
- Encrypted messages show placeholder text if password is unknown