Show Bluetooth permission alerts on launch and foreground (#765)

* Fix test suite peer ID collisions

Use unique peer IDs for each test suite to prevent global registry
collisions when Swift Testing runs suites in parallel.

- PrivateChatE2ETests: PRIV_* prefix
- PublicChatE2ETests: PUB_* prefix
- Update all peer ID references to use actual instance IDs

This fixes the race condition where simplePublicMessage() was receiving
duplicate deliveries due to registry contamination.

* Add Bluetooth permission & state alerts on launch and foreground

Wire up existing Bluetooth alert infrastructure to show notifications
when Bluetooth is off, unauthorized, or unsupported.

Changes:
- Add didUpdateBluetoothState() to BitchatDelegate protocol
- BLEService now notifies delegate when Bluetooth state changes
- ChatViewModel implements delegate method to show alerts
- Check Bluetooth state on app launch (after 100ms delay)
- Check Bluetooth state when app comes to foreground
- Add getCurrentBluetoothState() method to BLEService

The UI alert already existed but wasn't wired up. Now users will see
appropriate alerts for:
- Bluetooth turned off
- Bluetooth permission denied
- Bluetooth unsupported on device

Alert includes a button to open Settings on iOS.

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
jack
2025-10-06 22:47:11 +02:00
committed by GitHub
co-authored by jack
parent af6703cf24
commit b5b05977fb
5 changed files with 46 additions and 5 deletions
+25 -2
View File
@@ -549,7 +549,16 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
// Start mesh service immediately
meshService.startServices()
// Check initial Bluetooth state after a brief delay to allow centralManager initialization
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in
guard let self = self else { return }
if let bleService = self.meshService as? BLEService {
let state = bleService.getCurrentBluetoothState()
self.updateBluetoothState(state)
}
}
// Announce Tor status (geohash-only; do not show in mesh chat). Only when auto-start is allowed.
if TorManager.shared.torEnforced && !torStatusAnnounced && TorManager.shared.isAutoStartAllowed() {
torStatusAnnounced = true
@@ -2834,6 +2843,12 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
@MainActor
@objc private func appDidBecomeActive() {
// Check Bluetooth state and show alert if needed
if let bleService = meshService as? BLEService {
let currentState = bleService.getCurrentBluetoothState()
updateBluetoothState(currentState)
}
// When app becomes active, send read receipts for visible private chat
if let peerID = selectedPrivateChatPeer {
// Try immediately
@@ -4597,8 +4612,16 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
}
// Mention parsing moved from BLE use the existing non-optional helper below
// MARK: - Bluetooth State Monitoring
func didUpdateBluetoothState(_ state: CBManagerState) {
Task { @MainActor in
updateBluetoothState(state)
}
}
// MARK: - Peer Connection Events
func didConnectToPeer(_ peerID: String) {
SecureLogger.debug("🤝 Peer connected: \(peerID)", category: .session)