diff --git a/example/lib/home/scanner_screen.dart b/example/lib/home/scanner_screen.dart index ec51509..2b0b415 100644 --- a/example/lib/home/scanner_screen.dart +++ b/example/lib/home/scanner_screen.dart @@ -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 { } } - 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 { 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 { ), ), ), - 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 { 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 { ? colorScheme.onError : colorScheme.onPrimary, padding: const EdgeInsets.symmetric( - horizontal: 16, + horizontal: 12, vertical: 12, ), shape: RoundedRectangleBorder( diff --git a/example/lib/home/widgets/drawer.dart b/example/lib/home/widgets/drawer.dart index dc4a1b0..a5d8bc5 100644 --- a/example/lib/home/widgets/drawer.dart +++ b/example/lib/home/widgets/drawer.dart @@ -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 { ), ), ), + 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 { ); } + 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: diff --git a/example/lib/home/widgets/scanned_devices_placeholder_widget.dart b/example/lib/home/widgets/scanned_devices_placeholder_widget.dart index ed220a7..e6b1ca5 100644 --- a/example/lib/home/widgets/scanned_devices_placeholder_widget.dart +++ b/example/lib/home/widgets/scanned_devices_placeholder_widget.dart @@ -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( diff --git a/example/lib/peripheral_details/peripheral_detail_page.dart b/example/lib/peripheral_details/peripheral_detail_page.dart index c84bcd9..c64fc9d 100644 --- a/example/lib/peripheral_details/peripheral_detail_page.dart +++ b/example/lib/peripheral_details/peripheral_detail_page.dart @@ -36,7 +36,6 @@ class _PeripheralDetailPageState extends State { List discoveredServices = []; final List _logs = []; final binaryCode = TextEditingController(); - bool _isLoading = false; bool _isDiscoveringServices = false; bool _isDeviceInfoExpanded = false; bool _isDeviceActionsExpanded = true; @@ -407,18 +406,11 @@ class _PeripheralDetailPageState extends State { Future 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 { 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 { ? colorScheme.onError : colorScheme.onPrimary, padding: const EdgeInsets.symmetric( - horizontal: 16, + horizontal: 12, vertical: 12, ), shape: RoundedRectangleBorder( @@ -584,72 +576,6 @@ class _PeripheralDetailPageState extends State { ), ), ), - Visibility.maintain( - visible: _isLoading, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: AlwaysStoppedAnimation( - 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(