Commit Graph
586 Commits
Author SHA1 Message Date
6fbf7eee25 Refactor/ble nostr boundaries (#449)
* Refactor: move Nostr embedding and TLVs out of BLE; add NostrEmbeddedBitChat, Packets, PeerIDUtils; centralize MessageDeduplicator; update ChatViewModel to use new helpers; remove AI_CONTEXT.md and CLAUDE.md

* Rename class to BLEService with compatibility alias; move mention parsing out of BLE; emit low-level BLE events to delegate; unify hex helpers; accept 64-hex in isPeerConnected; add PeerIDResolver

* Project: rename file to BLEService.swift and update Xcode project; keep typealias SimplifiedBluetoothService = BLEService for compatibility

* Remove SimplifiedBluetoothService alias; update app code to use BLEService explicitly

* Tests: rename MockSimplifiedBluetoothService to MockBLEService; update typealiases and Xcode project

* Docs: update comments to refer to BLEService (tests, protocol, noise service)

* Tests: rename SimplifiedBluetoothServiceTests to BLEServiceTests; update project references and class names

* Introduce Transport protocol; BLEService conforms; document delegate-only event pattern in BLEService; keep publishers internal for UnifiedPeerService

* Adopt Transport end-to-end: add TransportPeerSnapshot + publishers; BLEService maps to Transport snapshots; UnifiedPeerService consumes Transport; ChatViewModel holds Transport

* Fix Transport integration: replace getPeerFingerprint with getFingerprint(for:); update PrivateChatManager and CommandProcessor to use Transport; add BLEService.getFingerprint(for:); update PeerManager to use Transport

* Refactor transport and BLE/Nostr layers; unify UI events; fix MainActor isolation

- Rename SimplifiedBluetoothService to BLEService and slim responsibilities
- Introduce Transport protocol and peerEventsDelegate for UI updates
- Add NostrTransport and MessageRouter to route PM/read/favorite via BLE or Nostr
- Centralize TLVs, PeerID utils, and MessageDeduplicator outside BLE
- Update UnifiedPeerService and ChatViewModel to use Transport and delegate events
- Fix MainActor isolation: route delegate calls via Task on MainActor; update notifyUI helper
- Adjust related files and tests accordingly

* BLEService: remove internal publishers; switch to delegate-only events

- Drop legacy messages/peers/fullPeers publishers
- Provide lightweight peerSnapshotSubject only to satisfy Transport
- Rework publishFullPeerData to build snapshots from internal state and notify delegate + subject
- Remove all peersPublisher.send call sites
- Keep UnifiedPeerService on delegate updates exclusively

* Remove inlined Nostr send helpers from ChatViewModel; route via MessageRouter

- Replace direct Nostr sends (PM, ACKs, favorites) with MessageRouter
- Add router method for delivery ACKs and implement NostrTransport.sendDeliveryAck
- Simplify ChatViewModel favorite notification path to use router
- Keep Nostr receive handling intact; reduce duplication

* Fix ReadReceipt initializer usage in ChatViewModel (readerID + readerNickname)

* Fix unused variable warning: replace shadowed 'nostrPubkey' bind with boolean check in ChatViewModel

* Fix queued PM format: use TLV for pending messages after Noise handshake

- Pending messages (including first-time favorite notifications) now use the same TLV encoding as normal sends
- Ensures ChatViewModel can decode on first send, even if handshake completes after queuing

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-17 15:17:04 +02:00
3ebfa85e90 Feature/nostr embedded bitchat (#448)
* UI: prefer mesh radio icon when connected; map short peer ID to full Noise key; rename ephemeral mapping to shortIDToNoiseKey; ensure header flips to purple globe on disconnect and keeps name.

* chore: stop tracking build artifacts; ignore .DerivedData and .Result*

* logging: add global threshold via BITCHAT_LOG_LEVEL and demote chatty logs to debug; keep critical errors/warnings and key state transitions

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-17 11:25:42 +02:00
fb1988ac27 BLE privacy: derive peerID from Noise fingerprint; remove BLE Local Name from advertising; verify announces against key-derived ID; auto-initiate Noise handshake when encrypted message arrives without session; drop rotating alias option. (#447)
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-17 02:20:49 +02:00
845ffc601b Refactor/robustness (#446)
* Refactor BitChat for improved robustness and performance

Major refactoring to simplify architecture and fix critical issues:

Architecture Improvements:
- Replace complex BluetoothMeshService with simplified SimplifiedBluetoothService
- Consolidate message routing and peer management into unified services
- Remove redundant caching layers and optimize performance

Bug Fixes:
- Fix critical BLE peer mapping corruption in mesh networks
- Fix encrypted message routing failures in multi-peer scenarios
- Fix app freezes and Main Thread Checker warnings
- Fix BLE message delivery in dual-role connections
- Fix favorite toggle UI not updating instantly
- Fix Nostr offline messaging with 24-hour message filtering

Features:
- Add command processor for chat commands
- Add autocomplete service for mentions and commands
- Improve private chat management with dedicated service
- Add unified peer service for consistent state management

Performance:
- Optimize BLE reconnection speed
- Reduce excessive logging throughout codebase
- Improve message deduplication efficiency
- Optimize UI updates and state management

* Improvements refactor robust (#441)

* remove unused code

* remove more

* TLV for announcement

* restore

* restore

* restore?

* messages tlv too (#442)

* Fix Nostr notification and read receipt issues, add TLV encoding, cleanup unused code

## Notification & Read Receipt Fixes
- Fixed toolbar notification icon appearing incorrectly on app restart for already-read messages
- Fixed read receipts being incorrectly deleted on startup when privateChats was empty
- Fixed messages not being marked as read when opening chat for first time
- Fixed senderPeerID not being updated during message consolidation
- Added startup phase logic to block old messages (>30s) while allowing recent ones
- Fixed unread status checking across all storage locations (ephemeral, stable Noise keys, temporary Nostr IDs)

## TLV Encoding Implementation
- Implemented Type-Length-Value encoding for private message payloads
- Added PrivateMessagePacket struct with TLV encode/decode methods
- Enhanced message structure for better extensibility and robustness

## Code Cleanup
- Removed unused PeerStateManager class and related dependencies
- Removed dead protocol types (DeliveryAck, ProtocolAck/Nack, NoiseIdentityAnnouncement)
- Cleaned up BitchatDelegate by removing unused methods
- Removed excessive debug logging throughout ChatViewModel
- Added test-only ProtocolNack helper for integration tests

## Technical Details
- Messages stored under three ID types: ephemeral peer IDs, stable Noise key hexes, temporary Nostr IDs
- Fixed cleanupOldReadReceipts() to skip when privateChats is empty or during startup
- Updated message consolidation to properly update senderPeerID
- Restored NIP-17 timestamp randomization (±15 minutes) for privacy

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
2025-08-17 01:51:54 +02:00
Mateusz MatoszkoandGitHub 47b0829685 Excludes Index.noindex in Justfile (#440) 2025-08-15 23:06:37 +02:00
Mario NachbaurandGitHub 030d6e0f11 Allow unicode letter characters in nicknames (#435) 2025-08-12 20:08:53 +02:00
db3c3b77f5 Remove dead store-and-forward and message aggregation code (#438)
- Remove completely unused message aggregation system (100% dead code)
- Remove broken store-and-forward implementation that only worked for relayed messages to offline favorites
- Update documentation to reflect actual functionality
- Net reduction of 312 lines of unmaintained code

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-12 20:08:37 +02:00
jack 26bcdf72d7 Merge remote-tracking branch 'origin/main' into code-cleanup 2025-08-12 11:43:52 +02:00
275f0ebaaf Remove dead code and simplify codebase (#436)
* refactor: remove dead code and consolidate system messages

- Delete 3 unused functions in ShareViewController (36 lines)
- Extract addSystemMessage() helper to eliminate duplication (120+ lines)
- Remove 22 'let _ =' wasteful computations across multiple files
- Net reduction of 215 lines of dead/duplicate code
- Improves maintainability and reduces technical debt

* fix: remove remaining unused variables to eliminate compiler warnings

- Remove unused senderNoiseKey in ChatViewModel
- Remove unused lastSuccess variable in BluetoothMeshService
- Eliminates all compiler warnings related to unused values

* refactor: remove all dead legacy and migration code

- Remove unused migrateSession() functions (never called in production)
  - NoiseSession.migrateSession() - 13 lines
  - NoiseEncryptionService.migratePeerSession() - 18 lines
  - Test for migration functionality - 17 lines

- Remove unnecessary keychain cleanup code (no legacy data existed)
  - cleanupLegacyKeychainItems() - 62 lines
  - aggressiveCleanupLegacyItems() - 72 lines
  - resetCleanupFlag() - 4 lines
  - Simplified panic mode to just use deleteAllKeychainData()

Total removed: 194 lines of dead/unnecessary code

Analysis revealed:
- KeychainManager introduced July 5, 2025
- Cleanup code added July 15, 2025 (10 days later)
- Legacy service names were never used in production
- Migration functions were incomplete implementation never called
- Peer ID rotation remains active (not legacy)

* Remove dead code and simplify codebase

- Remove unused BinaryEncodable protocol and BinaryMessageType enum
- Delete MockNoiseSession.swift (never used in tests)
- Remove all relay detection code (hardcoded to false)
  - Removed isRelayConnected property from BitchatPeer
  - Removed relayConnected case from ConnectionState enum
  - Cleaned up relay-related UI indicators in ContentView
  - Removed relay status checks from ChatViewModel
- Simplified peer connection logic by removing relay layer

Total: 169 lines removed across 5 files

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-12 11:33:08 +02:00
jack f4b8168ef9 Remove dead code and simplify codebase
- Remove unused BinaryEncodable protocol and BinaryMessageType enum
- Delete MockNoiseSession.swift (never used in tests)
- Remove all relay detection code (hardcoded to false)
  - Removed isRelayConnected property from BitchatPeer
  - Removed relayConnected case from ConnectionState enum
  - Cleaned up relay-related UI indicators in ContentView
  - Removed relay status checks from ChatViewModel
- Simplified peer connection logic by removing relay layer

Total: 169 lines removed across 5 files
2025-08-12 11:03:31 +02:00
jack 63f05b5d7e refactor: remove all dead legacy and migration code
- Remove unused migrateSession() functions (never called in production)
  - NoiseSession.migrateSession() - 13 lines
  - NoiseEncryptionService.migratePeerSession() - 18 lines
  - Test for migration functionality - 17 lines

- Remove unnecessary keychain cleanup code (no legacy data existed)
  - cleanupLegacyKeychainItems() - 62 lines
  - aggressiveCleanupLegacyItems() - 72 lines
  - resetCleanupFlag() - 4 lines
  - Simplified panic mode to just use deleteAllKeychainData()

Total removed: 194 lines of dead/unnecessary code

Analysis revealed:
- KeychainManager introduced July 5, 2025
- Cleanup code added July 15, 2025 (10 days later)
- Legacy service names were never used in production
- Migration functions were incomplete implementation never called
- Peer ID rotation remains active (not legacy)
2025-08-12 10:15:05 +02:00
jack a36eda3fbe fix: remove remaining unused variables to eliminate compiler warnings
- Remove unused senderNoiseKey in ChatViewModel
- Remove unused lastSuccess variable in BluetoothMeshService
- Eliminates all compiler warnings related to unused values
2025-08-12 09:43:06 +02:00
jack 99c0f6523e refactor: remove dead code and consolidate system messages
- Delete 3 unused functions in ShareViewController (36 lines)
- Extract addSystemMessage() helper to eliminate duplication (120+ lines)
- Remove 22 'let _ =' wasteful computations across multiple files
- Net reduction of 215 lines of dead/duplicate code
- Improves maintainability and reduces technical debt
2025-08-12 09:41:12 +02:00
7a7c89e689 Remove protocol versioning and handshake logic (#433)
Simplified the protocol by removing version negotiation and handshake sequences.
All devices now use protocol version 1 without negotiation. This eliminates
unnecessary connection overhead and complexity while maintaining full
compatibility across the network.

Changes:
- Removed versionHello and versionAck message types
- Simplified connection flow to use announce packets only
- Removed version negotiation state tracking
- Cleaned up handshake timeout logic
- Reduced connection establishment overhead

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-12 02:24:34 +02:00
3226b9cd14 Optimize logging to reduce verbosity while preserving critical network events (#432)
- Remove excessive verbose logging (DISCOVERY, INCOMING, PEER-UPDATE, etc.)
- Preserve critical network state logs (RESTORE, handshake failures, security events)
- Change routine key operations from info to debug level
- Add successful peer connection log after handshake completion
- Fix compiler warnings for unused variables
- Achieve ~95% reduction in log volume while maintaining debugging capability

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-11 23:45:59 +02:00
ChrisandGitHub 04c2b0caa6 fix: add secp256k1 dependency to resolve spm import error (#429) 2025-08-11 22:09:19 +02:00
callebtcandGitHub 29f1308e37 relay all packages (#431) 2025-08-11 22:05:25 +02:00
Alex RadandGitHub c6c186c77b Prevent spoofable plaintext messages from sliding into private chats (#428) 2025-08-11 17:05:36 +02:00
Mario NachbaurandGitHub d4262fab6c Remove noisy at symbol in mention (#420) 2025-08-08 18:41:50 +02:00
7876c8d96f Fix network flakiness and improve peer discovery (#405)
- Extend timeouts for better stability (availability: 30s->60s, cleanup: 3min->5min)
- Enable 30% relay probability for small networks to help discovery
- Add macOS-specific fixes for CoreBluetooth compatibility
- Implement rescan rate limiting to prevent battery drain
- Add comprehensive debug logging for network diagnostics
- Fix peripheral mapping and connection state management
- Improve relay-only session handling

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-05 10:13:41 +02:00
Steve LeeandGitHub 397c9f182b Clarify how packet loss is avoided with gossip protocol (#403)
Fixes an inaccurate description of Bloom filters and packet loss. Instead provides the actual reason to mitigate packet loss.
2025-08-04 22:32:15 +02:00
3ed37dfd0b Improve UI interactions (#390)
- Increase tap target size for back button in private message view
- Limit @mentions autocomplete to top 4 matches for better usability

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-02 11:48:19 +02:00
327fca9cb1 Remove cover traffic functionality (#389)
- Remove cover traffic variables and timer
- Remove cover traffic methods (startCoverTraffic, scheduleCoverTraffic, sendDummyMessage, generateDummyContent)
- Remove cover traffic initialization in startSession()
- Remove cover traffic check in handleReceivedPacket
- Remove timer invalidation in reset()
- Update README.md and AI_CONTEXT.md to remove cover traffic mentions

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-02 11:36:20 +02:00
871456896d Remove connection/disconnection system messages (#386)
- Remove system messages for peer connections to reduce chat noise
- Keep essential state management (ephemeral sessions, read receipts)
- Users can still see who's online via /w command

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-01 22:05:29 +02:00
b4b22e0e05 Add Bluetooth status alerts (#385)
- Add alert UI to notify users when Bluetooth is off/unauthorized
- Monitor Bluetooth state changes in BluetoothMeshService
- Show appropriate messages for different Bluetooth states
- Add Settings button to open system settings on iOS
- Check initial Bluetooth state on app startup

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-01 21:51:32 +02:00
jack 8ec39f566d Fix runtime crashes and reduce excessive logging
- Fix Dictionary crash in ChatViewModel by adding deduplication logic for peer IDs
- Fix compilation errors: PeerData -> BitchatPeer type correction
- Fix Task async context issue with cancellables
- Remove excessive debug logging for handshake coordination
- Remove repetitive keep-alive timer logs
- Remove version cache logging spam
2025-08-01 21:39:09 +02:00
jack 172b06721b Revert "Fix compilation errors in ChatViewModel"
This reverts commit e2d50e3684.
2025-08-01 20:26:28 +02:00
jack e2d50e3684 Fix compilation errors in ChatViewModel
- Fixed PeerData type reference (should be BitchatPeer)
- Fixed Task initialization in init() method with proper async/await syntax
- Fixed cancellables binding issue with proper unwrapping
- Maintained duplicate peer ID protection in peerIndex dictionary
2025-08-01 20:24:09 +02:00
jack d605a0b6db Fix crash from duplicate peer IDs in Dictionary initialization
- Added deduplication logic in ChatViewModel to handle duplicate peer IDs gracefully
- Enhanced PeerManager to prevent duplicate peers by tracking both nicknames and IDs
- Added final safety check to ensure no duplicates in peers array
- This fixes crash when Dictionary(uniqueKeysWithValues:) encounters duplicate keys
2025-08-01 19:04:36 +02:00
jack 1d698c2006 Fix @Unknown entries in autocomplete by improving nickname resolution
- Added getBestAvailableNickname() method to resolve nicknames from multiple sources
- Updated all PeerSession creations to use better nickname resolution
- Changed fallback from 'Unknown' to 'anon[peerID]' format for distinguishability
- Modified getPeerNicknames() to proactively update Unknown entries
- This ensures autocomplete shows meaningful nicknames instead of @Unknown
2025-08-01 19:01:07 +02:00
jack a92828471b Fix App Store submission: remove invalid background-processing from UIBackgroundModes 2025-08-01 16:58:13 +02:00
jack 69c8161cf8 Fix crash in BinaryProtocol.decode due to out-of-bounds data access
- Add comprehensive bounds checking before all data access operations
- Validate payload lengths don't exceed available data
- Protect against integer overflow in size calculations
- Handle malformed compressed packets gracefully
- Add extensive test coverage for edge cases

This fixes crashes when receiving malformed Bluetooth packets that claim
payload sizes larger than the actual data available.
2025-08-01 16:52:21 +02:00
aa1ecf40fc Fix iOS background Bluetooth connectivity issues (#378)
- Implement Core Bluetooth state restoration with restoration identifiers
- Add background task management to protect critical BLE operations
- Fix aggressive battery optimization that killed background connectivity
- Disable scan duty cycling in background (was causing 89-97% downtime)
- Add missing didEnterBackground/willEnterForeground notifications
- Fix advertising cutoff in low battery conditions (now only <10%)
- Add background-processing entitlement to Info.plist
- Optimize scan parameters for background vs foreground modes

These changes address the issue where devices lose mesh connectivity when
the app is backgrounded, ensuring continuous Bluetooth operation within
iOS background execution limits.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-01 12:18:14 +02:00
b004bfa4aa Remove message batching system for simpler, faster UI updates (#377)
- Remove dual-timer batching architecture (100ms message timer, 50ms UI timer)
- Delete pending message queues and all batching infrastructure
- Simplify to direct message appends with duplicate detection
- Trust SwiftUI's built-in update optimization instead of manual batching
- Results in instant message display and 208 lines of code removed
- Eliminates timer management complexity and potential race conditions

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-01 11:38:53 +02:00
a6c2e751d2 Performance optimizations: LazyVStack, UI batching, timer consolidation (#375)
- Replace VStack with LazyVStack for message list to enable on-demand rendering
- Batch UI updates in ChatViewModel to reduce main thread operations
- Consolidate 12 timers into 3 (high/medium/low frequency) in BluetoothMeshService
- Fix thread safety in scheduleUIUpdate with main thread check

These changes significantly improve app responsiveness and reduce CPU usage.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-01 01:05:59 +02:00
8f32edaa64 Security fixes and improvements (#374)
- Fix force unwrapping in NostrIdentity bech32 functions that could crash on non-ASCII input
- Add comprehensive input validation for all protocol messages (peer IDs, nicknames, timestamps)
- Strengthen keychain security with better sandbox detection and consistent app group usage
- Implement secure memory clearing for cryptographic keys and shared secrets
- Fix panic mode not reconnecting to mesh by restarting services after emergency disconnect

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-07-31 23:42:08 +02:00
Mateusz MatoszkoandGitHub 5a44b32719 Adds swift-secp256k1 to project.yml (#366) 2025-07-31 21:24:03 +02:00
jackandGitHub d85c9e226b Update README.md 2025-07-31 18:13:51 +02:00
jack f953c50565 Remove 'back' text from PM view, keep only chevron 2025-07-31 12:43:28 +02:00
2a081f65fc Group Connectivity Improvements (#365)
* Implement dynamic connection limits based on network size

Fixes connection thrashing in group scenarios by dynamically adjusting the connection limit based on the number of nearby peers.

Changes:
- Replace fixed maxConnectedPeripherals with dynamic calculation
- Maintain full mesh connectivity for small groups (<10 peers)
- Scale connection limit up to 2x for larger groups
- Override battery-based limits when needed to prevent thrashing
- Add logging to track dynamic limit changes

This solves the "perfect storm" issue where 6-8 people would constantly disconnect/reconnect when the power saver mode limited connections to 5.

* Implement optimistic version negotiation with caching

Skip version negotiation for known peers by caching negotiated versions for 24 hours.

Changes:
- Add version cache that persists beyond session lifetime
- Check cache before sending version hello
- Skip negotiation entirely for cached peers (instant connection)
- Cache cleanup runs every 60 seconds
- Invalidate cache on protocol errors for automatic fallback
- Log when using cached versions

This reduces protocol messages by ~40% for reconnecting peers and enables instant connections for known devices.

* Fix unused variable warning

* Implement protocol message deduplication

Suppress duplicate protocol messages within configurable time windows to reduce overhead.

Changes:
- Add deduplication tracker with per-message-type time windows
- Suppress duplicate announces within 5 seconds
- Suppress duplicate version negotiations within 10 seconds
- Track messages by peer ID and optional content hash
- Automatic cleanup of expired entries every 60 seconds
- Log when duplicates are suppressed

This reduces protocol message overhead by 20-30% in group scenarios where multiple connection attempts trigger redundant announcements and version negotiations.

* Fix MessageType enum case name

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-07-31 11:36:49 +02:00
jack 71b7f8edd3 Fix whitespace and project file updates 2025-07-31 11:34:51 +02:00
jack 46fd1d23d9 Remove duplicate libsecp256k1 import
P256K already includes libsecp256k1, so importing both was redundant and doubled the library size in the app bundle.
2025-07-31 10:53:43 +02:00
jack 6a9a1cdb3b Fix duplicate Nostr relay connections
Add check to prevent creating multiple WebSocket connections to the same relay when connect() is called multiple times during app startup.
2025-07-31 10:48:22 +02:00
VasilyKaiserandGitHub c74d6ad75e Update README.md (#360)
Add deepwiki link for developers who will consider contributing, to easily see how app is structured and other details.
2025-07-31 01:03:31 +02:00
jackandGitHub 439fb59fdd Update README.md 2025-07-31 01:00:13 +02:00
jackandGitHub 0a5e4b248f Update README.md 2025-07-31 00:58:57 +02:00
jack b6e6f0f63b Fix unused variable warnings in NostrProtocol.swift
Replace unused variable names with _ to silence compiler warnings:
- ephemeralPubkey calculation (line 40)
- senderPubkey calculation (line 216)
- timestamp formatter strings (lines 452-453, 456-457)
v1.2.0
2025-07-30 23:22:02 +02:00
a97d5c2d5e Implement Nostr NIP-17 for offline messaging and performance optimizations (#358)
* Implement Nostr NIP-17 integration for offline mutual favorite messaging

- Add Nostr relay connectivity and NIP-17 gift-wrapped private messages
- Implement dual transport system: Bluetooth mesh + Nostr relays
- Add favorites persistence with mutual detection and Nostr key exchange
- Support offline messaging for mutual favorites via Nostr relays
- Handle peer identity rotation with automatic favorite key updates
- Fix UI to show all favorites (online and offline) in peer list
- Add proper message routing based on peer availability
- Update peer list icons: 📶 for mesh, 🌐 for Nostr, 🌙 for one-sided
- Fix toolbar display for offline peers in private chat view
- Add network entitlements for macOS and iOS
- Implement automatic noise key updates when peers reconnect

* Implement Nostr NIP-17 for private messaging between mutual favorites

- Add support for NIP-17 gift-wrapped private messages with double encryption
- Enable private messaging via Nostr when mutual favorites are offline
- Fix peer reconnection issues: users now stay in private chat when peer reconnects
- Fix read receipt delivery: send pending receipts when peer comes back online
- Add message ID tracking through Nostr transport for proper delivery acknowledgments
- Update peer noise key mapping when peers reconnect with different IDs
- Check for Nostr messages when app becomes active
- Implement 7-day message retrieval window for better reliability

* Fix private message UI refresh and adjust PEOPLE header spacing

- Fix UI not updating when receiving private messages on mesh
  - Add immediate batch processing for messages in active chat
  - Force UI update when viewing current chat peer
  - Ensure real-time message display without navigation
- Reduce PEOPLE header spacing from 16 to 12 points for tighter UI

* Fix build errors and unused value warnings in Nostr favorites integration

* Implement read receipts via Nostr

- Added sendReadReceipt method to MessageRouter to send receipts via mesh or Nostr
- Added handleReadReceipt to process incoming read receipts from Nostr
- Made ReadReceipt.readerID mutable to allow updates
- Added missing notification names and error cases
- Uncommented and enabled read receipt handling in ChatViewModel
- Read receipts now work seamlessly via both mesh and Nostr transports

* Fix ReadReceipt initialization - use correct constructor

* Implement persistent message deduplication for Nostr

- Added ProcessedMessagesService to track messages across app restarts
- Store processed message IDs and last timestamp in UserDefaults
- Skip already processed messages when receiving from Nostr
- Adjust subscription filter to use smart timestamp (last processed or 24h)
- Prevents duplicate messages when reconnecting to Nostr relays

* Fix peer list UI not updating to Nostr mode on disconnect

- Remove peer from peerNicknames when connection state changes to disconnected
- Ensures UI properly reflects peer disconnection state
- Peer list now correctly shows Nostr mode (🌐) when peer walks out of range

* Update peer count to include Nostr peers and improve UI indicators

- Peer count now shows total peers including those available via Nostr
- Count appears purple when only Nostr peers are connected
- Private message header shows purple globe icon for Nostr transport
- Consistent visual language for Nostr connectivity across the app

* Improve RSSI real-time updates and fix UI flashing

- Reduce RSSI update timer from 10s to 5s and per-peripheral from 5s to 3s
- Add RSSI change detection with 2 dBm threshold for responsive updates
- Always update previous RSSI values to fix gradual change detection bug
- Trigger RSSI read on peer authentication for immediate status
- Fix UI flashing 'nobody around' by removing array clearing on updates
- Add proper cleanup of RSSI tracking on disconnect and peer rotation

* Fix favorite nickname updates and peer list filtering

- Add updateNickname method to FavoritesPersistenceService to update nicknames while preserving favorite status
- Update announce handler to check for existing favorites and update their nicknames
- Remove dead BluetoothMeshService+PublicAPI.swift file
- Move sendFavoriteNotification to main BluetoothMeshService
- Fix peer list to only show connected peers and user's favorites (not peers who favorite the user)
- Remove UI logic for showing peers who favorite us but we don't favorite back

* Remove dead code and fix ghost connections

Phase 1 - Remove abandoned peer ID rotation code:
- Remove previousPeerID property and rotationGracePeriod constant
- Remove grace period logic from isPeerIDOurs()
- Remove previousPeerID handling from announce packets
- Pass nil for previousPeerID in identity announcements

Phase 2 - Fix ghost connections from relayed packets:
- CRITICAL FIX: Only add peers to activePeers if they have a peripheral connection
- Check for peripheral connection before marking peer as active
- Prevents ghost connections when announce packets are relayed
- Log warning when rejecting relayed announce without peripheral

Phase 3 - Begin consolidating redundant peer tracking:
- Create new PeerSession class to unify peer data in one place
- Add helper methods for PeerSession management
- Integrate PeerSession into announce packet handling
- Update authentication state changes to use PeerSession
- Update peripheral mapping and RSSI to sync with PeerSession
- Update disconnect and leave handling to update PeerSession
- Add consolidated getter methods for peer info

This fixes the issue where peers appeared connected without actually having a Bluetooth connection, and begins the migration to a cleaner single-source-of-truth peer tracking system.

* Fix multiple connect messages on peer restart

- Move hasPeripheralConnection check outside sync block to fix scope issue
- Add debug logging to track connect message conditions
- Ensure connect messages only show on first connection or reconnection with peripheral

* Optimize RSSI updates for better battery life

- Add app state tracking to BluetoothMeshService
- Only update RSSI when app is in foreground and peer list is visible
- Add setPeerListVisible method to control RSSI updates
- Remove individual periodic RSSI updates in favor of centralized timer
- Update ContentView to notify mesh service of peer list visibility changes
- Improve battery efficiency by avoiding unnecessary RSSI reads

* Initialize peer list visibility state on view appear

- Ensure RSSI timer state is properly initialized when view loads
- Call setPeerListVisible with initial showSidebar value

* Fix duplicate peers and multiple disconnect messages

- Fixed duplicate peer entries when relay-connected by adding relay-connected peers to connectedNicknames set
- Added deduplication logic for disconnect messages with 2-second window to prevent multiple disconnect notifications for same peer
- Added cleanup for old disconnect notification tracking to prevent memory growth

* Fix peer count indicator color logic

- Show green for any mesh peer (direct Bluetooth or relay connected)
- Show purple only for Nostr-only peers (no mesh connections)
- Show red only when no peers are reachable at all
- Fixed to use meshPeerCount instead of viewModel.isConnected which only checked direct connections

* Fix relay connection issues and peripheral mapping cleanup

- Fixed relay-connected peers being marked as directly connected when receiving identity announce
- Added proper cleanup of temp peripheral mappings when discovering real peer ID
- Fixed disconnect notification deduplication cleanup
- Improved debug logging to show actual connection state (direct/relay/nostr/offline)
- Added debug logging for relay connection detection
- Fixed compiler warning about unused variable

* Fix Unknown peer disconnect notifications and disable faulty relay detection

- Add check to prevent disconnect notifications for Unknown peers that never announced
- Disable relay connection detection until proper relay tracking is implemented
- In a 2-peer network, peers should never show as relay-connected

* Fix RSSI updates and peer visibility after reconnection

- Add updatePeers() call in didUpdatePeerList to refresh RSSI values in UI
- Track version hello times to better detect direct connections
- Allow peers to be marked active if recent version hello received
- Fix thread safety for version hello tracking
- Clean up old version hello times to prevent memory leaks

* Remove RSSI tracking completely and replace with radio icon for mesh connections

* Fix build errors after RSSI removal

- Add missing peripheralID declaration in didDiscover delegate method
- Remove obsolete setPeerListVisible calls from ContentView

* Center private message header elements using ZStack layout

- Replace HStack with ZStack for perfect centering
- Globe/nick/lock cluster now always centered regardless of button sizes
- Back and favorite buttons positioned in overlay HStack

* Fix private chat view showing Unknown when peer reconnects with new ID

- Update FavoritesPersistenceService to notify with both old and new keys
- Handle peer ID changes in ChatViewModel to migrate private chat data
- Update selectedPrivateChatPeer when favorite's noise key changes
- Maintain chat history and unread status across peer ID changes

* Fix read receipts after peer reconnection and replace nos.lol relay

- Updated sendReadReceipt to resolve current peer ID when peers reconnect with new IDs
- Enhanced MessageRouter to check favorites for current noise keys
- Replaced nos.lol relay with relay.snort.social to avoid PoW requirements

* Fix message routing to use Nostr when peers are disconnected

Changed message routing logic to check actual peer connection status using
isPeerConnected() instead of just checking if peer exists in nickname list.
This ensures that offline mutual favorites correctly route messages through
Nostr instead of attempting Bluetooth handshakes.

Also added safety check to prevent starting private chat with ourselves.

* Add debug logging for Nostr timestamp randomization

Added logging to track the random offset being applied to Nostr event
timestamps to debug why messages appear 8-9 minutes in the future.

* Fix Nostr timestamp issue by reducing randomization range

Temporarily reduced the timestamp randomization from +/-15 minutes to +/-1 minute
to address messages appearing 8-9 minutes in the future. Added detailed UTC/local
time logging to help debug the issue.

The random offset should have been evenly distributed but was consistently
showing positive offsets. This change mitigates the issue while we investigate
the root cause.

* Fix message routing for offline favorites and reduce Nostr timestamp randomization

- Fix transport selection to properly detect disconnected peers using isPeerConnected()
- Change from checking peer nicknames to checking actual connection status
- Reduce Nostr timestamp randomization from ±15 minutes to ±1 minute
- Add detailed timestamp logging for debugging

* Improve PM header UI and encryption status display

- Show transport icons (radio/link/globe) in PM header matching peer list
- Always show lock icon if noise session ever established (no handshake icon)
- Change verified icon from shield to checkmark seal
- Use consistent green color (textColor) for PM header and encryption icons

* Update AI_CONTEXT.md with comprehensive Nostr implementation details

- Add Nostr and MessageRouter to architecture diagram
- Document NIP-17 gift wrap implementation
- Explain favorites integration and mutual requirement
- Detail message routing logic and transport selection
- Add security considerations and debugging tips
- Update common tasks with Nostr-specific guidance

* Fix data consistency issues in favorites, chat migration, and bloom filter

- Fix favorites deduplication to use public key instead of nickname
  Prevents losing favorites when multiple peers use same nickname

- Fix private chat migration to use fingerprints instead of nicknames
  Prevents merging unrelated conversations that share nicknames
  Fallback to nickname matching only for legacy data without fingerprints

- Fix bloom filter reset to preserve messages from last 10 minutes
  Prevents duplicate message processing after bloom filter resets
  Keeps processedMessages for 10 minutes while bloom filter resets every 5

* Add mutual favorites internet messaging to app info

* Remove excessive debug/info logging for production readiness

- Removed ~140 debug/info level logs across core services
- Preserved critical logs: errors, warnings, security events, state changes
- Kept logs for: peer join/leave, favorite status, mutual relationships
- Cleaned up verbose logging in: Bluetooth mesh, Nostr, message routing
- Improved performance by reducing log I/O overhead

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Implement performance optimizations and fix build warnings

- Add UI update debouncing (50ms) to prevent excessive SwiftUI refreshes
- Implement memory bounds for processedMessages with LRU eviction
- Add encryption queue cleanup for disconnected peers
- Optimize peer lookups from O(n) to O(1) with indexed dictionary
- Fix multiple compiler warnings (unused variables, missing break statements)
- Optimize peer counting with single-pass reduce operation
- Fix ViewBuilder control flow issue in ContentView
- Fix Dictionary initialization type mismatches with Array wrapper

* Add TTL-based cleanup for Noise handshake sessions

- Add session TTL (5 minutes) and max session limit (50) to NoiseHandshakeCoordinator
- Clean up old established sessions to prevent unbounded memory growth
- Move handshake cleanup timer out of DEBUG conditional for production use
- Run cleanup every 60 seconds in production (vs 30s in debug)
- Clean up crypto state immediately on peer disconnect
- Prevents memory leaks from accumulating Noise sessions

* Pre-compute and store fingerprints in PeerSession for O(1) lookups

- Store fingerprint in PeerSession when peer authenticates
- Update getPeerFingerprint() and getFingerprint() to check PeerSession first
- Replace all noiseService.getPeerFingerprint() calls with optimized version
- Eliminates repeated SHA256 calculations during message processing
- Improves performance for favorite checks and encryption status updates

* Implement exponential backoff for Nostr relay connections

- Add reconnection tracking fields to Relay struct (attempts, timing)
- Replace fixed 5-second delay with exponential backoff (1s → 2s → 4s... max 5min)
- Stop reconnection attempts after 10 failures to prevent infinite retries
- Reset attempt counter on successful connection
- Add utility methods: retryConnection(), getRelayStatuses(), resetAllConnections()
- DNS failures still bypass retry logic as before
- Improves battery life and reduces server load from constant reconnection attempts

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-30 23:14:17 +02:00
Tim JohnsenandGitHub a438c46817 Disable sharing images via extension, not supported at the moment. (#346) 2025-07-29 17:48:50 +02:00
jackandGitHub 41810ad419 Update README.md 2025-07-28 16:49:46 +02:00