feat: ui rework and gear generator
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:abawo_bt_app/controller/shifter_device_telemetry.dart';
|
||||
import 'package:abawo_bt_app/model/firmware_file_selection.dart';
|
||||
import 'package:abawo_bt_app/model/shifter_types.dart';
|
||||
import 'package:abawo_bt_app/service/firmware_file_selection_service.dart';
|
||||
@ -69,6 +70,8 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
||||
String? _gearRatiosError;
|
||||
List<double> _gearRatios = const [];
|
||||
int _defaultGearIndex = 0;
|
||||
bool _isDeviceTelemetryLoading = false;
|
||||
bool _hasLoadedDeviceTelemetry = false;
|
||||
|
||||
late final FirmwareFileSelectionService _firmwareFileSelectionService;
|
||||
FirmwareUpdateService? _firmwareUpdateService;
|
||||
@ -195,6 +198,9 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
||||
if (!_hasLoadedGearRatios && !_isGearRatiosLoading) {
|
||||
unawaited(_loadGearRatios());
|
||||
}
|
||||
if (!_hasLoadedDeviceTelemetry && !_isDeviceTelemetryLoading) {
|
||||
unawaited(_loadDeviceTelemetry());
|
||||
}
|
||||
return;
|
||||
}
|
||||
final asyncBluetooth = ref.read(bluetoothProvider);
|
||||
@ -238,6 +244,7 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
||||
_shifterService = service;
|
||||
});
|
||||
unawaited(_loadGearRatios());
|
||||
unawaited(_loadDeviceTelemetry());
|
||||
}
|
||||
|
||||
Future<void> _showPairingRecoveryDialog() async {
|
||||
@ -276,6 +283,8 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
||||
await _disposeFirmwareUpdateService();
|
||||
await _shifterService?.dispose();
|
||||
_shifterService = null;
|
||||
_isDeviceTelemetryLoading = false;
|
||||
_hasLoadedDeviceTelemetry = false;
|
||||
}
|
||||
|
||||
Future<void> _disposeFirmwareUpdateService() async {
|
||||
@ -285,6 +294,34 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
||||
_firmwareUpdateService = null;
|
||||
}
|
||||
|
||||
Future<void> _loadDeviceTelemetry({bool force = false}) async {
|
||||
final shifter = _shifterService;
|
||||
if (shifter == null || _isDeviceTelemetryLoading) {
|
||||
return;
|
||||
}
|
||||
if (_hasLoadedDeviceTelemetry && !force) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isDeviceTelemetryLoading = true;
|
||||
final result = await shifter.readDeviceTelemetry();
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isDeviceTelemetryLoading = false;
|
||||
if (result.isErr()) {
|
||||
_hasLoadedDeviceTelemetry = false;
|
||||
return;
|
||||
}
|
||||
|
||||
ref.read(shifterDeviceTelemetryCacheProvider.notifier).upsert(
|
||||
widget.deviceAddress,
|
||||
result.unwrap(),
|
||||
);
|
||||
_hasLoadedDeviceTelemetry = true;
|
||||
}
|
||||
|
||||
Future<void> _loadGearRatios() async {
|
||||
final shifter = _shifterService;
|
||||
if (shifter == null || _isGearRatiosLoading || _isFirmwareUpdateBusy) {
|
||||
@ -539,6 +576,11 @@ class _DeviceDetailsPageState extends ConsumerState<DeviceDetailsPage> {
|
||||
_firmwareUserMessage = result.unwrapErr().toString();
|
||||
}
|
||||
});
|
||||
|
||||
if (result.isOk()) {
|
||||
_hasLoadedDeviceTelemetry = false;
|
||||
unawaited(_loadDeviceTelemetry(force: true));
|
||||
}
|
||||
}
|
||||
|
||||
String _dfuPhaseText(DfuUpdateState state) {
|
||||
@ -1208,6 +1250,11 @@ Widget _buildDeviceOverviewCard(
|
||||
required CentralStatus? status,
|
||||
}) {
|
||||
final asyncSavedDevices = ref.watch(nConnectedDevicesProvider);
|
||||
final telemetry = ref.watch(
|
||||
shifterDeviceTelemetryCacheProvider.select(
|
||||
(cache) => cache[deviceAddress],
|
||||
),
|
||||
);
|
||||
|
||||
return asyncSavedDevices.when(
|
||||
data: (devices) {
|
||||
@ -1229,12 +1276,11 @@ Widget _buildDeviceOverviewCard(
|
||||
);
|
||||
}
|
||||
|
||||
// TODO(yannik): Replace these overview placeholder metrics with actual
|
||||
// battery, signal, and firmware values once the device exposes them.
|
||||
return _DeviceOverviewCard(
|
||||
device: currentDeviceData,
|
||||
connectionStatus: connectionStatus,
|
||||
status: status,
|
||||
telemetry: telemetry,
|
||||
);
|
||||
},
|
||||
loading: () => const Card(
|
||||
@ -1257,11 +1303,13 @@ class _DeviceOverviewCard extends StatelessWidget {
|
||||
required this.device,
|
||||
required this.connectionStatus,
|
||||
required this.status,
|
||||
required this.telemetry,
|
||||
});
|
||||
|
||||
final ConnectedDevice device;
|
||||
final ConnectionStatus connectionStatus;
|
||||
final CentralStatus? status;
|
||||
final ShifterDeviceTelemetry? telemetry;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -1317,27 +1365,27 @@ class _DeviceOverviewCard extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
Row(
|
||||
children: const [
|
||||
children: [
|
||||
Expanded(
|
||||
child: _OverviewMetricTile(
|
||||
label: 'Battery',
|
||||
value: '--',
|
||||
value: telemetry?.batteryLabel ?? '--',
|
||||
icon: Icons.battery_charging_full_rounded,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Expanded(
|
||||
const SizedBox(width: 10),
|
||||
const Expanded(
|
||||
child: _OverviewMetricTile(
|
||||
label: 'Signal',
|
||||
value: 'Ready',
|
||||
icon: Icons.signal_cellular_alt_rounded,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: _OverviewMetricTile(
|
||||
label: 'Firmware',
|
||||
value: '--',
|
||||
value: telemetry?.firmwareLabel ?? '--',
|
||||
icon: Icons.memory_rounded,
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user