From 4fceb0c69018df74b999fcdfe3fe604886f3396e Mon Sep 17 00:00:00 2001 From: Yandrik Date: Tue, 5 May 2026 21:06:11 +0200 Subject: [PATCH] feat: better pairing broken notification --- lib/pages/device_details_page.dart | 5 +++++ lib/pages/devices_page.dart | 5 ++--- lib/pages/devices_tab_page.dart | 3 +++ lib/util/bluetooth_settings.dart | 7 ++++++- test/util/bluetooth_settings_test.dart | 23 +++++++++++++++++++++++ 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 test/util/bluetooth_settings_test.dart diff --git a/lib/pages/device_details_page.dart b/lib/pages/device_details_page.dart index abfde59..e042f90 100644 --- a/lib/pages/device_details_page.dart +++ b/lib/pages/device_details_page.dart @@ -732,6 +732,11 @@ class _DeviceDetailsPageState extends ConsumerState { } if (result.isErr()) { + if (isBluetoothPairingRecoveryError(result.unwrapErr())) { + await showBluetoothPairingRecoveryDialog(context); + return; + } + ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( diff --git a/lib/pages/devices_page.dart b/lib/pages/devices_page.dart index 2dd1a44..950428f 100644 --- a/lib/pages/devices_page.dart +++ b/lib/pages/devices_page.dart @@ -116,12 +116,11 @@ class _ConnectDevicePageState extends ConsumerState { } break; case Err(:final v): - final error = v.toString(); - if (error.toLowerCase().contains('disconnected')) { + if (isBluetoothPairingRecoveryError(v)) { await showBluetoothPairingRecoveryDialog(context); } else { ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Connection unsuccessful:\n$error')), + SnackBar(content: Text('Connection unsuccessful:\n$v')), ); } break; diff --git a/lib/pages/devices_tab_page.dart b/lib/pages/devices_tab_page.dart index 5b32283..7b141e3 100644 --- a/lib/pages/devices_tab_page.dart +++ b/lib/pages/devices_tab_page.dart @@ -8,6 +8,7 @@ import 'package:abawo_bt_app/model/firmware_file_selection.dart'; import 'package:abawo_bt_app/model/shifter_types.dart'; import 'package:abawo_bt_app/pages/bootloader_recovery_update_page.dart'; import 'package:abawo_bt_app/service/firmware_file_selection_service.dart'; +import 'package:abawo_bt_app/util/bluetooth_settings.dart'; import 'package:flutter/material.dart'; import 'package:flutter_reactive_ble/flutter_reactive_ble.dart' show DiscoveredDevice, ScanMode, Uuid; @@ -586,6 +587,8 @@ class _SavedDevicesListState extends ConsumerState<_SavedDevicesList> { } context.push('/device/${device.deviceAddress}'); + } else if (isBluetoothPairingRecoveryError(result.unwrapErr())) { + await showBluetoothPairingRecoveryDialog(context); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( diff --git a/lib/util/bluetooth_settings.dart b/lib/util/bluetooth_settings.dart index 974bce9..4ec9066 100644 --- a/lib/util/bluetooth_settings.dart +++ b/lib/util/bluetooth_settings.dart @@ -3,6 +3,10 @@ import 'dart:io'; import 'package:app_settings/app_settings.dart'; import 'package:flutter/material.dart'; +bool isBluetoothPairingRecoveryError(Object error) { + return error.toString().toLowerCase().contains('disconnected'); +} + Future openBluetoothSettings() async { try { if (Platform.isAndroid) { @@ -23,7 +27,8 @@ Future showBluetoothPairingRecoveryDialog(BuildContext context) { final content = isIOS ? 'The connection opened, then broke while reading the device. This is probably a pairing problem.\n\nGo to Settings, then Bluetooth, then forget this device. After that, come back and connect again.\n\nOr press Open Settings below. From the app settings page, press Back twice to reach Bluetooth settings, then forget this device.' : 'The connection opened, then broke while reading the device. This is probably a pairing problem.\n\nOpen Bluetooth settings, remove/forget this device, then come back and connect again.'; - final settingsButtonLabel = isIOS ? 'Open Settings' : 'Open Bluetooth settings'; + final settingsButtonLabel = + isIOS ? 'Open Settings' : 'Open Bluetooth settings'; return showDialog( context: context, diff --git a/test/util/bluetooth_settings_test.dart b/test/util/bluetooth_settings_test.dart new file mode 100644 index 0000000..a1972d9 --- /dev/null +++ b/test/util/bluetooth_settings_test.dart @@ -0,0 +1,23 @@ +import 'package:abawo_bt_app/util/bluetooth_settings.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('isBluetoothPairingRecoveryError', () { + test('detects immediate disconnect connection failures', () { + expect( + isBluetoothPairingRecoveryError( + 'Failed to connect to device-id: disconnected', + ), + isTrue, + ); + }); + + test('does not classify generic connection failures as pairing recovery', + () { + expect( + isBluetoothPairingRecoveryError('Timed out connecting to device-id'), + isFalse, + ); + }); + }); +}