Refactor Bluetooth availability handling in ScannerScreen and AppDrawer
- Removed the tooltip for Bluetooth availability from ScannerScreen and integrated the BleAvailabilityIcon directly into the AppDrawer. - Updated the AppDrawer to accept Bluetooth availability state and a callback for state changes. - Simplified button labels in ScannerScreen and ScannedDevicesPlaceholderWidget for clarity. - Adjusted padding for buttons to enhance UI consistency.
This commit is contained in:
@@ -7,7 +7,6 @@ import 'package:universal_ble/universal_ble.dart';
|
||||
import 'package:universal_ble_example/data/company_identifier_service.dart';
|
||||
import 'package:universal_ble_example/data/mock_universal_ble.dart';
|
||||
import 'package:universal_ble_example/data/scan_controller.dart';
|
||||
import 'package:universal_ble_example/home/widgets/ble_availability_icon.dart';
|
||||
import 'package:universal_ble_example/home/widgets/drawer.dart';
|
||||
import 'package:universal_ble_example/home/widgets/scan_filter_widget.dart';
|
||||
import 'package:universal_ble_example/home/widgets/scanned_devices_placeholder_widget.dart';
|
||||
@@ -370,25 +369,6 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
String _getBluetoothAvailabilityTooltip() {
|
||||
switch (bleAvailabilityState) {
|
||||
case AvailabilityState.poweredOn:
|
||||
return 'Bluetooth is on';
|
||||
case AvailabilityState.poweredOff:
|
||||
return 'Bluetooth is off';
|
||||
case AvailabilityState.resetting:
|
||||
return 'Bluetooth is resetting';
|
||||
case AvailabilityState.unauthorized:
|
||||
return 'Bluetooth permission denied';
|
||||
case AvailabilityState.unsupported:
|
||||
return 'Bluetooth not supported';
|
||||
case AvailabilityState.unknown:
|
||||
return 'Bluetooth status unknown';
|
||||
case null:
|
||||
return 'Checking Bluetooth status...';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void setState(VoidCallback fn) {
|
||||
if (mounted) super.setState(fn);
|
||||
@@ -429,6 +409,13 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
||||
UniversalBle.queueType = _queueType;
|
||||
});
|
||||
},
|
||||
availabilityState: bleAvailabilityState,
|
||||
onAvailabilityStateChanged: (state) {
|
||||
setState(() => bleAvailabilityState = state);
|
||||
if (state == AvailabilityState.poweredOn) {
|
||||
_tryAutoStartScan();
|
||||
}
|
||||
},
|
||||
),
|
||||
appBar: AppBar(
|
||||
title: Row(
|
||||
@@ -477,18 +464,6 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Tooltip(
|
||||
message: _getBluetoothAvailabilityTooltip(),
|
||||
triggerMode: TooltipTriggerMode.tap,
|
||||
child: BleAvailabilityIcon(onAvailabilityStateChanged: (state) {
|
||||
setState(() => bleAvailabilityState = state);
|
||||
// Auto-start scanning when Bluetooth becomes available
|
||||
if (state == AvailabilityState.poweredOn) {
|
||||
_tryAutoStartScan();
|
||||
}
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
elevation: 0,
|
||||
@@ -519,7 +494,7 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
||||
size: 20,
|
||||
),
|
||||
label: Text(
|
||||
_scanController?.isScanning == true ? 'Stop Scan' : 'Start Scan',
|
||||
_scanController?.isScanning == true ? 'Stop' : 'Scan',
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -535,7 +510,7 @@ class _ScannerScreenState extends State<ScannerScreen> {
|
||||
? colorScheme.onError
|
||||
: colorScheme.onPrimary,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
horizontal: 12,
|
||||
vertical: 12,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:universal_ble/universal_ble.dart';
|
||||
import 'package:universal_ble_example/home/widgets/ble_availability_icon.dart';
|
||||
import 'package:universal_ble_example/home/scanner_screen.dart';
|
||||
import 'package:universal_ble_example/home/system_devices_screen.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
@@ -9,11 +10,15 @@ import 'package:url_launcher/url_launcher.dart';
|
||||
class AppDrawer extends StatefulWidget {
|
||||
final QueueType? queueType;
|
||||
final Function(QueueType)? onQueueTypeChanged;
|
||||
final AvailabilityState? availabilityState;
|
||||
final void Function(AvailabilityState)? onAvailabilityStateChanged;
|
||||
|
||||
const AppDrawer({
|
||||
super.key,
|
||||
this.queueType,
|
||||
this.onQueueTypeChanged,
|
||||
this.availabilityState,
|
||||
this.onAvailabilityStateChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -62,6 +67,14 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.availabilityState != null &&
|
||||
widget.onAvailabilityStateChanged != null)
|
||||
ListTile(
|
||||
leading: BleAvailabilityIcon(
|
||||
onAvailabilityStateChanged: widget.onAvailabilityStateChanged!,
|
||||
),
|
||||
title: Text(_getBluetoothAvailabilityLabel(widget.availabilityState!)),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.search),
|
||||
title: const Text('Scanner'),
|
||||
@@ -180,6 +193,23 @@ class _AppDrawerState extends State<AppDrawer> {
|
||||
);
|
||||
}
|
||||
|
||||
String _getBluetoothAvailabilityLabel(AvailabilityState state) {
|
||||
switch (state) {
|
||||
case AvailabilityState.poweredOn:
|
||||
return 'Bluetooth is on';
|
||||
case AvailabilityState.poweredOff:
|
||||
return 'Bluetooth is off';
|
||||
case AvailabilityState.resetting:
|
||||
return 'Bluetooth is resetting';
|
||||
case AvailabilityState.unauthorized:
|
||||
return 'Bluetooth permission denied';
|
||||
case AvailabilityState.unsupported:
|
||||
return 'Bluetooth not supported';
|
||||
case AvailabilityState.unknown:
|
||||
return 'Bluetooth state unknown';
|
||||
}
|
||||
}
|
||||
|
||||
String _getQueueTypeLabel(QueueType queueType) {
|
||||
switch (queueType) {
|
||||
case QueueType.global:
|
||||
|
||||
@@ -52,7 +52,7 @@ class ScannedDevicesPlaceholderWidget extends StatelessWidget {
|
||||
onPressed: onTap,
|
||||
icon: const Icon(Icons.play_arrow, size: 24),
|
||||
label: const Text(
|
||||
'Start Scan',
|
||||
'Scan',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -62,7 +62,7 @@ class ScannedDevicesPlaceholderWidget extends StatelessWidget {
|
||||
backgroundColor: colorScheme.primary,
|
||||
foregroundColor: colorScheme.onPrimary,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 32,
|
||||
horizontal: 12,
|
||||
vertical: 16,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
|
||||
@@ -36,7 +36,6 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
List<BleService> discoveredServices = [];
|
||||
final List<String> _logs = [];
|
||||
final binaryCode = TextEditingController();
|
||||
bool _isLoading = false;
|
||||
bool _isDiscoveringServices = false;
|
||||
bool _isDeviceInfoExpanded = false;
|
||||
bool _isDeviceActionsExpanded = true;
|
||||
@@ -407,18 +406,11 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
Future<T> Function() action, {
|
||||
Function(dynamic error)? onError,
|
||||
}) async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
try {
|
||||
return await action();
|
||||
} catch (e) {
|
||||
onError?.call(e);
|
||||
rethrow;
|
||||
} finally {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,7 +552,7 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
size: 20,
|
||||
),
|
||||
label: Text(
|
||||
_scanController!.isScanning ? 'Stop Scan' : 'Start Scan',
|
||||
_scanController!.isScanning ? 'Stop' : 'Scan',
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -574,7 +566,7 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
? colorScheme.onError
|
||||
: colorScheme.onPrimary,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
horizontal: 12,
|
||||
vertical: 12,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
@@ -584,72 +576,6 @@ class _PeripheralDetailPageState extends State<PeripheralDetailPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Visibility.maintain(
|
||||
visible: _isLoading,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (deviceType != DeviceType.desktop)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Icon(
|
||||
isConnected
|
||||
? Icons.bluetooth_connected
|
||||
: Icons.bluetooth_disabled,
|
||||
color: isConnected
|
||||
? Colors.green
|
||||
: colorScheme.onSurface.withValues(alpha: 0.6),
|
||||
size: 20,
|
||||
),
|
||||
)
|
||||
else
|
||||
Container(
|
||||
margin: const EdgeInsets.only(right: 16),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: isConnected
|
||||
? Colors.green.withValues(alpha: 0.2)
|
||||
: Colors.orange.withValues(alpha: 0.2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
isConnected
|
||||
? Icons.check_circle
|
||||
: Icons.bluetooth_disabled,
|
||||
size: 16,
|
||||
color: isConnected
|
||||
? Colors.green.shade700
|
||||
: Colors.orange.shade700,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
isConnected ? 'Connected' : 'Disconnected',
|
||||
style: TextStyle(
|
||||
color: isConnected
|
||||
? Colors.green.shade700
|
||||
: Colors.orange.shade700,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Row(
|
||||
|
||||
Reference in New Issue
Block a user