Skip to content

Commit bffae57

Browse files
committed
move most device state providers into known devices notifier
1 parent 92a6d33 commit bffae57

25 files changed

+222
-284
lines changed

lib/Backend/Bluetooth/bluetooth_manager_plus.dart

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import '../device_registry.dart';
2525
import '../firmware_update.dart';
2626
import '../logging_wrappers.dart';
2727
import '../sensors.dart';
28-
import 'bluetooth_manager.dart';
28+
import 'known_devices.dart';
2929
import 'bluetooth_message.dart';
3030

3131
part 'bluetooth_manager_plus.g.dart';
@@ -505,15 +505,15 @@ class Scan extends _$Scan {
505505
ScanReason build() {
506506
isScanningStreamSubscription = FlutterBluePlus.isScanning.listen(onIsScanningChange);
507507

508-
ref.listen(isAllKnownGearConnectedProvider, isAllKnownGearConnectedProviderListener);
509-
510508
Hive.box(settings).listenable(keys: [hasCompletedOnboarding])
511509
..removeListener(isAllGearConnectedListener)
512510
..addListener(isAllGearConnectedListener);
513511
isBluetoothEnabled
514512
..removeListener(isAllGearConnectedListener)
515513
..addListener(isAllGearConnectedListener);
516-
514+
KnownDevices.instance
515+
..removeListener(isAllGearConnectedListener)
516+
..addListener(isAllGearConnectedListener);
517517
// Has to be delayed so the provider initializes before calling the listener. Otherwise we can't call ref or set state in other methods
518518
Future.delayed(Duration(milliseconds: 1), () => isAllGearConnectedListener());
519519

@@ -524,12 +524,6 @@ class Scan extends _$Scan {
524524
return ScanReason.notScanning;
525525
}
526526

527-
void isAllKnownGearConnectedProviderListener(bool? previous, bool next) {
528-
if (ref.mounted) {
529-
isAllGearConnectedListener();
530-
}
531-
}
532-
533527
void onIsScanningChange(bool isScanning) {
534528
if (state != ScanReason.notScanning && !isScanning) {
535529
state = ScanReason.notScanning;
@@ -561,7 +555,7 @@ class Scan extends _$Scan {
561555
}
562556

563557
void isAllGearConnectedListener() {
564-
bool allConnected = ref.read(isAllKnownGearConnectedProvider);
558+
bool allConnected = KnownDevices.instance.isAllGearConnected;
565559
bool isInOnboarding = HiveProxy.getOrDefault(settings, hasCompletedOnboarding, defaultValue: hasCompletedOnboardingDefault) < hasCompletedOnboardingVersionToAgree;
566560
if ((!allConnected || isInOnboarding) && isBluetoothEnabled.value) {
567561
beginScan(scanReason: ScanReason.background);
@@ -574,7 +568,7 @@ class Scan extends _$Scan {
574568
enum ScanReason { background, addGear, notScanning }
575569

576570
Future<void> sendMessage(BaseStatefulDevice device, List<int> message, {bool withoutResponse = false}) async {
577-
if (!_didInitFlutterBluePlus) {
571+
if (!_didInitFlutterBluePlus || device.baseStoredDevice.btMACAddress.startsWith("DEV")) {
578572
return;
579573
}
580574
BluetoothDevice? bluetoothDevice = FlutterBluePlus.connectedDevices.firstWhereOrNull((element) => element.remoteId.str == device.baseStoredDevice.btMACAddress);

lib/Backend/Bluetooth/bluetooth_manager.dart renamed to lib/Backend/Bluetooth/known_devices.dart

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,63 @@ class KnownDevices with ChangeNotifier {
5151
Future<void> store() async {
5252
await HiveProxy.clear<BaseStoredDevice>(devicesBox);
5353
await HiveProxy.addAll<BaseStoredDevice>(devicesBox, state.values.map((e) => e.baseStoredDevice));
54-
notifyListeners();
54+
_notify();
55+
56+
_onDevicePaired();
5557
}
5658

5759
Future<void> removeDevGear() async {
5860
_state = _state.rebuild((p0) => p0.removeWhere((p0, p1) => p0.contains("DEV")));
5961
await store();
6062
}
63+
64+
// Helpers for gear connected
65+
66+
void _notify() {
67+
notifyListeners();
68+
}
69+
70+
BuiltList<BaseStatefulDevice> get connectedGear {
71+
return KnownDevices.instance.state.values
72+
.where((element) => element.deviceConnectionState.value == ConnectivityState.connected)
73+
.where(
74+
// don't consider gear connected until services have been discovered
75+
(element) => element.bluetoothUartService.value != null,
76+
)
77+
.toBuiltList();
78+
}
79+
80+
bool get isAllGearConnected {
81+
return connectedGear.length == state.length;
82+
}
83+
BuiltSet<DeviceType> get connectedGearTypes {
84+
return connectedGear.map((e) => e.baseDeviceDefinition.deviceType).toBuiltSet();
85+
}
86+
87+
BuiltList<BaseStatefulDevice> getKnownGearForType(BuiltSet<DeviceType> deviceTypes) {
88+
return state.values.where((element) => deviceTypes.contains(element.baseDeviceDefinition.deviceType)).toBuiltList();
89+
}
90+
91+
BuiltList<BaseStatefulDevice> getConnectedGearForType(BuiltSet<DeviceType> deviceTypes) {
92+
return connectedGear.where((element) => deviceTypes.contains(element.baseDeviceDefinition.deviceType)).toBuiltList();
93+
}
94+
95+
BuiltList<BaseStatefulDevice> get connectedIdleGear {
96+
return connectedGear.where((element) => element.deviceState.value == DeviceState.standby).toBuiltList();
97+
}
98+
99+
BuiltList<BaseStatefulDevice> getConnectedIdleGearForType(BuiltSet<DeviceType> deviceTypes) {
100+
return connectedIdleGear.where((element) => deviceTypes.contains(element.baseDeviceDefinition.deviceType)).toBuiltList();
101+
}
102+
103+
void _onDevicePaired() {
104+
for (BaseStatefulDevice baseStatefulDevice in KnownDevices.instance.state.values) {
105+
baseStatefulDevice.deviceConnectionState
106+
..removeListener(_notify)
107+
..addListener(_notify);
108+
baseStatefulDevice.bluetoothUartService
109+
..removeListener(_notify)
110+
..addListener(_notify);
111+
}
112+
}
61113
}

lib/Backend/Definitions/Action/base_action.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ enum ActionCategory {
1717
@HiveField(5)
1818
glowtip,
1919
@HiveField(7)
20-
hidden,
20+
hidden, // used as a sub-action for legacy ear moves
2121
@HiveField(8)
2222
audio,
2323
@HiveField(9)

lib/Backend/Definitions/Device/device_definition.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import 'package:tail_app/Backend/dynamic_config.dart';
1212

1313
import '../../../Frontend/translation_string_definitions.dart';
1414
import '../../../constants.dart';
15-
import '../../Bluetooth/bluetooth_manager.dart';
15+
import '../../Bluetooth/known_devices.dart';
1616
import '../../firmware_update.dart';
1717
import '../../logging_wrappers.dart';
1818
import '../../version.dart';

lib/Backend/action_registry.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
55
import 'package:riverpod_annotation/riverpod_annotation.dart';
66
import 'package:tail_app/Frontend/utils.dart';
77

8-
import 'Bluetooth/bluetooth_manager.dart';
8+
import 'Bluetooth/known_devices.dart';
99
import 'Definitions/Action/base_action.dart';
1010
import 'Definitions/Device/device_definition.dart';
1111
import 'audio.dart';
12-
import 'device_registry.dart';
1312
import 'move_lists.dart';
1413

1514
part 'action_registry.g.dart';
@@ -218,7 +217,7 @@ class GetAvailableActions extends _$GetAvailableActions {
218217
BuiltMap<String, BuiltSet<BaseAction>> getState() {
219218
Map<String, Set<BaseAction>> sortedActions = {};
220219
final BuiltMap<String, BuiltSet<BaseAction>> allActions = ref.watch(getAllActionsProvider);
221-
final BuiltList<BaseStatefulDevice> availableGear = ref.watch(getAvailableGearProvider);
220+
final BuiltList<BaseStatefulDevice> availableGear = KnownDevices.instance.connectedGear;
222221
for (BaseAction baseAction in allActions.values.flattened) {
223222
Set<BaseAction>? baseActions = {};
224223
for (BaseStatefulDevice baseStatefulDevice in availableGear) {

lib/Backend/app_shortcuts.dart

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import 'package:built_collection/built_collection.dart';
22
import 'package:quick_actions/quick_actions.dart';
33
import 'package:riverpod_annotation/riverpod_annotation.dart';
4+
import 'package:tail_app/Backend/Bluetooth/known_devices.dart';
45
import 'package:tail_app/Backend/analytics.dart';
56
import 'package:tail_app/Backend/command_runner.dart';
67

78
import 'Definitions/Action/base_action.dart';
89
import 'Definitions/Device/device_definition.dart';
910
import 'action_registry.dart';
10-
import 'device_registry.dart';
1111
import 'favorite_actions.dart';
1212

1313
part 'app_shortcuts.g.dart';
@@ -20,7 +20,7 @@ Future<void> appShortcuts(Ref ref) async {
2020
quickActions.initialize((shortcutType) {
2121
BaseAction? action = ref.read(getActionFromUUIDProvider(shortcutType));
2222
if (action != null) {
23-
Iterable<BaseStatefulDevice> knownDevices = ref.read(getAvailableIdleGearProvider);
23+
Iterable<BaseStatefulDevice> knownDevices = KnownDevices.instance.connectedIdleGear;
2424
for (BaseStatefulDevice device in knownDevices) {
2525
ref.read(runActionProvider(device).notifier).runAction(action, triggeredBy: "App Shortcut");
2626
}
@@ -31,17 +31,7 @@ Future<void> appShortcuts(Ref ref) async {
3131
}
3232

3333
Future<void> updateShortcuts(BuiltList<FavoriteAction> favoriteActions, Ref ref) async {
34-
Iterable<BaseAction> allActions = favoriteActions
35-
.map(
36-
(e) => ref.read(getActionFromUUIDProvider(e.actionUUID)),
37-
)
38-
.nonNulls;
34+
Iterable<BaseAction> allActions = favoriteActions.map((e) => ref.read(getActionFromUUIDProvider(e.actionUUID))).nonNulls;
3935

40-
quickActions.setShortcutItems(
41-
allActions
42-
.map(
43-
(e) => ShortcutItem(type: e.uuid, localizedTitle: e.name),
44-
)
45-
.toList(),
46-
);
36+
quickActions.setShortcutItems(allActions.map((e) => ShortcutItem(type: e.uuid, localizedTitle: e.name)).toList());
4737
}

lib/Backend/command_queue.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import 'dart:convert';
33

44
import 'package:collection/collection.dart';
55
import 'package:riverpod_annotation/riverpod_annotation.dart';
6-
import 'package:tail_app/Backend/Bluetooth/bluetooth_manager.dart';
6+
import 'package:tail_app/Backend/Bluetooth/known_devices.dart';
77
import 'package:tail_app/Backend/Bluetooth/bluetooth_manager_plus.dart';
88
import 'package:tail_app/Backend/command_history.dart';
99

@@ -20,7 +20,7 @@ enum CommandQueueState {
2020
delay, // The queue is momentarily paused
2121
blocked, // the queue is stopped
2222
idle, // inbetween moves
23-
empty // the queue is empty
23+
empty, // the queue is empty
2424
}
2525

2626
@Riverpod(keepAlive: true)
@@ -133,7 +133,7 @@ class CommandQueue extends _$CommandQueue {
133133
if (_internalCommandQueue.isEmpty) {
134134
_setState(CommandQueueState.empty);
135135
} else {
136-
runCommand(_internalCommandQueue.removeFirst());
136+
Future(() => runCommand(_internalCommandQueue.removeFirst()));
137137
}
138138
break;
139139
case CommandQueueState.empty:
@@ -163,7 +163,9 @@ class CommandQueue extends _$CommandQueue {
163163
} else {
164164
bluetoothLog.fine("Sending command to ${_device.baseStoredDevice.name}:${bluetoothMessage.message}");
165165
ref.read(commandHistoryProvider(_device).notifier).add(type: MessageHistoryType.send, message: bluetoothMessage.message);
166-
if (bluetoothMessage.responseMSG != null) {
166+
167+
// skip delay for dev gear but still add the command to the queue
168+
if (bluetoothMessage.responseMSG != null && !_device.baseStoredDevice.btMACAddress.startsWith("DEV")) {
167169
_setState(CommandQueueState.waitingForResponse);
168170
_runningCommandTimer = Timer(timeoutDuration, _onTimeout);
169171
}
@@ -176,7 +178,7 @@ class CommandQueue extends _$CommandQueue {
176178

177179
void addCommand(BluetoothMessage bluetoothMessage) {
178180
// Don't add commands to disconnected or dev gear.
179-
if (_device.deviceConnectionState.value != ConnectivityState.connected || _device.baseStoredDevice.btMACAddress.startsWith("DEV") || state == CommandQueueState.blocked) {
181+
if (_device.deviceConnectionState.value != ConnectivityState.connected || state == CommandQueueState.blocked) {
180182
return;
181183
}
182184
bluetoothLog.info("Adding command to queue $bluetoothMessage");

0 commit comments

Comments
 (0)