mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-09-19 04:59:59 +00:00
fix(nav): host the bluetooth receiver above the destinations
The ACTION_STATE_CHANGED receiver was registered from a DisposableEffect inside OnboardingFlowScreen. That was harmless while the when branch kept that composable on screen for chat too, but chat is its own destination now, so reaching COMPLETE took the onboarding entry out of composition and unregistered the only receiver watching the adapter. Turning Bluetooth off from Quick Settings while sitting in chat then went unnoticed, and the onResume fallback does not fire without a lifecycle transition. Reproduced on a Pixel 9a. Disabling Bluetooth on the chat route logged nothing on this branch, against main: D BluetoothStatusManager: Bluetooth turned OFF W MainActivity: Bluetooth disabled or failed: User has turned off their Blue Hoisted next to NavDisplay, which lives for as long as the Activity's composition, so it no longer depends on which destination is showing. The callback also reads onboardingState from the ViewModel rather than the value captured when the effect ran, which the effect's keys never invalidated. Same two lines now log on the chat route, and 591 unit tests pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MdKgoKZbL5K1wsn1WsES26
This commit is contained in:
parent
c0a8a3c6df
commit
1835281fc9
@ -179,6 +179,32 @@ class MainActivity : OrientationAwareActivity() {
|
||||
val onboardingState by mainViewModel.onboardingState.collectAsState()
|
||||
val root = rootRouteFor(onboardingState)
|
||||
|
||||
// Hosted here rather than in the onboarding destination: turning
|
||||
// Bluetooth off has to be noticed on the chat route too, and a
|
||||
// destination-scoped receiver is unregistered when its entry leaves
|
||||
// the back stack.
|
||||
val context = LocalContext.current
|
||||
DisposableEffect(context, bluetoothStatusManager) {
|
||||
val receiver = bluetoothStatusManager.monitorBluetoothState(
|
||||
context = context,
|
||||
bluetoothStatusManager = bluetoothStatusManager,
|
||||
onBluetoothStateChanged = { status ->
|
||||
if (status == BluetoothStatus.ENABLED &&
|
||||
mainViewModel.onboardingState.value == OnboardingState.BLUETOOTH_CHECK
|
||||
) {
|
||||
checkBluetoothAndProceed()
|
||||
}
|
||||
}
|
||||
)
|
||||
onDispose {
|
||||
try {
|
||||
context.unregisterReceiver(receiver)
|
||||
} catch (e: IllegalStateException) {
|
||||
Log.w("BluetoothStatusUI", "Receiver was not registered")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keyed on root, so this fires only when the app crosses between
|
||||
// onboarding and chat — not on every step within onboarding.
|
||||
// resetTo rather than goTo: onboarding must not be reachable with
|
||||
@ -246,7 +272,6 @@ class MainActivity : OrientationAwareActivity() {
|
||||
|
||||
@Composable
|
||||
private fun OnboardingFlowScreen(modifier: Modifier = Modifier) {
|
||||
val context = LocalContext.current
|
||||
val onboardingState by mainViewModel.onboardingState.collectAsState()
|
||||
val bluetoothStatus by mainViewModel.bluetoothStatus.collectAsState()
|
||||
val locationStatus by mainViewModel.locationStatus.collectAsState()
|
||||
@ -256,27 +281,6 @@ class MainActivity : OrientationAwareActivity() {
|
||||
val isLocationLoading by mainViewModel.isLocationLoading.collectAsState()
|
||||
val isBatteryOptimizationLoading by mainViewModel.isBatteryOptimizationLoading.collectAsState()
|
||||
|
||||
DisposableEffect(context, bluetoothStatusManager) {
|
||||
|
||||
val receiver = bluetoothStatusManager.monitorBluetoothState(
|
||||
context = context,
|
||||
bluetoothStatusManager = bluetoothStatusManager,
|
||||
onBluetoothStateChanged = { status ->
|
||||
if (status == BluetoothStatus.ENABLED && onboardingState == OnboardingState.BLUETOOTH_CHECK) {
|
||||
checkBluetoothAndProceed()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onDispose {
|
||||
try {
|
||||
context.unregisterReceiver(receiver)
|
||||
} catch (e: IllegalStateException) {
|
||||
Log.w("BluetoothStatusUI", "Receiver was not registered")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (onboardingState) {
|
||||
OnboardingState.PERMISSION_REQUESTING -> {
|
||||
InitializingScreen(modifier)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user