Files
abawo-bt-app/lib/pages/home_page.dart

223 lines
6.9 KiB
Dart

import 'package:abawo_bt_app/controller/bluetooth.dart';
import 'package:abawo_bt_app/database/database.dart';
import 'package:abawo_bt_app/model/bluetooth_device_model.dart';
import 'package:abawo_bt_app/widgets/device_listitem.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Abawo BT App'),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () => context.go('/settings'),
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Welcome to Abawo BT App',
style: TextStyle(fontSize: 20),
),
const SizedBox(height: 20),
// Devices Section
Container(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Devices',
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w500),
),
IconButton(
icon: const Icon(Icons.add_circle),
onPressed: () => context.go('/connect_device'),
tooltip: 'Connect a device',
),
],
),
const SizedBox(height: 10),
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300),
borderRadius: BorderRadius.circular(8),
),
child: const Center(
child: DevicesList(),
),
),
],
),
),
const SizedBox(height: 30),
ElevatedButton(
onPressed: () => context.go('/settings'),
child: const Text('Go to Settings'),
),
],
),
),
);
}
}
class DevicesList extends ConsumerStatefulWidget {
const DevicesList({super.key});
@override
ConsumerState<DevicesList> createState() => _DevicesListState();
}
class _DevicesListState extends ConsumerState<DevicesList> {
String? _connectingDeviceId; // ID of device currently being connected
Future<void> _removeDevice(ConnectedDevice device) async {
final shouldRemove = await showDialog<bool>(
context: context,
builder: (dialogContext) => AlertDialog(
title: const Text('Remove device?'),
content:
Text('Do you want to remove ${device.deviceName} from the app?'),
actions: [
TextButton(
onPressed: () => Navigator.of(dialogContext).pop(false),
child: const Text('Cancel'),
),
FilledButton(
onPressed: () => Navigator.of(dialogContext).pop(true),
child: const Text('Remove'),
),
],
),
);
if (shouldRemove != true || !mounted) {
return;
}
final result = await ref
.read(nConnectedDevicesProvider.notifier)
.deleteConnectedDevice(device.id);
if (!mounted) {
return;
}
if (result.isErr()) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Failed to remove device: ${result.unwrapErr()}')),
);
return;
}
if (_connectingDeviceId == device.deviceAddress) {
setState(() {
_connectingDeviceId = null;
});
}
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('${device.deviceName} removed from the app.')),
);
}
@override
Widget build(BuildContext context) {
final asyncDevices = ref.watch(nConnectedDevicesProvider);
return asyncDevices.when(
loading: () => const Center(
child: CircularProgressIndicator(),
),
error: (error, stackTrace) => Center(
child: Text(
'Error loading devices: ${error.toString()}',
style: TextStyle(color: Colors.red),
textAlign: TextAlign.center,
),
),
data: (devices) {
if (devices.isEmpty) {
return const Center(
child: Text(
'No devices connected yet',
style: TextStyle(color: Colors.grey),
),
);
}
return ListView.builder(
itemCount: devices.length,
shrinkWrap: true,
itemBuilder: (context, index) {
final device = devices[index];
return InkWell(
onTap: () async {
if (_connectingDeviceId != null) return;
setState(() {
_connectingDeviceId = device.deviceAddress;
});
try {
final controller = await ref.read(bluetoothProvider.future);
final result = await controller.connectById(
device.deviceAddress,
timeout: const Duration(seconds: 10),
);
if (result.isOk()) {
context.go('/device/${device.deviceAddress}');
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Connection failed. Is the device turned on and in range?'),
duration: const Duration(seconds: 3),
),
);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${e.toString()}')),
);
} finally {
setState(() {
_connectingDeviceId = null;
});
}
},
child: DeviceListItem(
deviceName: device.deviceName,
deviceId: device.deviceAddress,
type: deviceTypeFromString(device.deviceType),
isConnecting: device.deviceAddress == _connectingDeviceId,
trailing: IconButton(
tooltip: 'Remove device',
icon: const Icon(Icons.delete_outline),
onPressed: () => _removeDevice(device),
),
),
);
},
);
},
);
}
}