feat: working connection, conn setting, and gear ratio setting for universal shifters
This commit is contained in:
@ -1,4 +1,9 @@
|
||||
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 {
|
||||
@ -53,10 +58,7 @@ class HomePage extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'No devices connected yet',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
child: DevicesList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -73,3 +75,148 @@ class HomePage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user