Skip to content

Commit 9733e46

Browse files
committed
update flutter and fix some bugs left from removing a provider
1 parent 819d1fe commit 9733e46

File tree

17 files changed

+341
-83
lines changed

17 files changed

+341
-83
lines changed

.github/actions/setup_build/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ inputs:
99
default: "zulu"
1010
flutter-version:
1111
description: "Flutter Version"
12-
default: "3.35.3"
12+
default: "3.35.7"
1313
ruby-version:
1414
description: "Ruby Version"
1515
default: "3.4"

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.3.1
1+
1.4.0

lib/Backend/Bluetooth/bluetooth_manager.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class KnownDevices with ChangeNotifier {
1616
BuiltMap<String, BaseStatefulDevice> get state => _state;
1717

1818
//https://stackoverflow.com/questions/12649573/how-do-you-build-a-singleton-in-dart
19-
static final KnownDevices instance = KnownDevices._internal();
19+
static final KnownDevices instance = KnownDevices._internal();
2020

2121
KnownDevices._internal() {
2222
BuiltList<BaseStoredDevice> storedDevices = HiveProxy.getAll<BaseStoredDevice>(devicesBox).toBuiltList();

lib/Backend/Definitions/Device/device_definition.dart

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import 'package:collection/collection.dart';
66
import 'package:fl_chart/fl_chart.dart';
77
import 'package:flutter/material.dart';
88
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
9-
import 'package:flutter_riverpod/flutter_riverpod.dart';
109
import 'package:freezed_annotation/freezed_annotation.dart';
1110
import 'package:hive_ce/hive.dart';
1211
import 'package:tail_app/Backend/dynamic_config.dart';
@@ -22,6 +21,8 @@ part 'device_definition.freezed.dart';
2221

2322
part 'device_definition.g.dart';
2423

24+
/// When adding new gear make sure to update `getNameFromBTName()`
25+
2526
@HiveType(typeId: 6)
2627
enum DeviceType {
2728
@HiveField(1)
@@ -32,6 +33,8 @@ enum DeviceType {
3233
wings,
3334
@HiveField(4)
3435
miniTail,
36+
@HiveField(5)
37+
claws,
3538
} //TODO extend with icon
3639

3740
@HiveType(typeId: 14)
@@ -82,6 +85,8 @@ extension DeviceTypeExtension on DeviceType {
8285
return deviceTypeWings();
8386
case DeviceType.miniTail:
8487
return deviceTypeMiniTail();
88+
case DeviceType.claws:
89+
return deviceTypeClawGear();
8590
}
8691
}
8792

@@ -102,6 +107,18 @@ extension DeviceTypeExtension on DeviceType {
102107
return Colors.blueAccent;
103108
case DeviceType.wings:
104109
return Colors.greenAccent;
110+
case DeviceType.claws:
111+
return Colors.deepPurpleAccent;
112+
}
113+
}
114+
115+
//mainly used to hide claws from the custom moves pages, since usermove/dssp isnt relevent there.
116+
bool isHidden() {
117+
switch (this) {
118+
case DeviceType.claws:
119+
return true;
120+
default:
121+
return false;
105122
}
106123
}
107124
}
@@ -382,6 +399,8 @@ String getNameFromBTName(String bluetoothDeviceName) {
382399
return 'FlutterWings';
383400
case '(!)Tail1':
384401
return 'DigiTail';
402+
case 'clawgear':
403+
return 'ClawGear';
385404
}
386405
return bluetoothDeviceName;
387406
}

lib/Backend/action_registry.dart

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@ part 'action_registry.g.dart';
1616

1717
@immutable
1818
class ActionRegistry {
19-
/// TODO: Changes needed for TAILCoNTROL
20-
/// Add DeviceType.ears to CommandAction actions
21-
/// Remove legacy EarMoveList and CommandAction.hiddenEars
22-
/// Add Ear action aliases
19+
static final BuiltSet<BaseAction> clawMoves = {
20+
CommandAction(name: "Extend Slow", command: "MOVE1", deviceCategory: [DeviceType.claws], response: "MOVE1 END", uuid: "a373f116-4c0a-4ab7-894d-caedc4e76d1d"),
21+
CommandAction(name: "Extend Fast", command: "MOVE2", deviceCategory: [DeviceType.claws], response: "MOVE2 END", uuid: "9446d5a2-7178-4177-ad61-29f7e8980791"),
22+
CommandAction(name: "1/2 Extend Slow", command: "MOVE3", deviceCategory: [DeviceType.claws], response: "MOVE3 END", uuid: "2eb1278a-d366-4406-99cd-26710dbd6417"),
23+
CommandAction(name: "1/2 Extend Fast", command: "MOVE4", deviceCategory: [DeviceType.claws], response: "MOVE4 END", uuid: "f17a781a-670e-4365-ba4b-18c8f503da56"),
24+
CommandAction(name: "Retract Slow", command: "MOVE5", deviceCategory: [DeviceType.claws], response: "MOVE5 END", uuid: "9074fb1f-1526-467e-8a84-a4752d9160f1"),
25+
CommandAction(name: "Retract Fast", command: "MOVE6", deviceCategory: [DeviceType.claws], response: "MOVE6 END", uuid: "08d19e6c-fed7-46b5-8c49-e019d74b5ac9"),
26+
CommandAction(name: "Rawr", command: "RAWR", deviceCategory: [DeviceType.claws], response: "RAWR END", uuid: "58b5465f-2f1b-492d-9390-ea0d43d2ee90"),
27+
}.build();
2328

2429
static final BuiltSet<BaseAction> earMoves = {
2530
//TailControl only
@@ -175,7 +180,14 @@ class ActionRegistry {
175180
CommandAction(name: "Rustles 3", command: "TAILT2", deviceCategory: [DeviceType.wings], response: "TAILT2 END", uuid: "5f7e16e4-04f6-46ab-bbc9-e6f908fc559c"),
176181
CommandAction(name: "Rustles 4", command: "TAILET", deviceCategory: [DeviceType.wings], response: "TAILET END", uuid: "0dfeb464-572b-452b-be4a-5a36affd2da9"),
177182
}.build();
178-
static final BuiltSet<BaseAction> allCommands = BuiltSet<BaseAction>().union(glowtipCommands).union(earMoves).union(flutterWingsMoves).union(miniTailMoves).union(tailMoves).union(rgbCommands);
183+
static final BuiltSet<BaseAction> allCommands = BuiltSet<BaseAction>()
184+
.union(glowtipCommands)
185+
.union(earMoves)
186+
.union(flutterWingsMoves)
187+
.union(miniTailMoves)
188+
.union(tailMoves)
189+
.union(rgbCommands)
190+
.union(clawMoves);
179191
}
180192

181193
@Riverpod(keepAlive: true)

lib/Backend/app_shortcuts.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import 'package:built_collection/built_collection.dart';
2-
import 'package:flutter/foundation.dart';
3-
import 'package:flutter_riverpod/flutter_riverpod.dart';
42
import 'package:quick_actions/quick_actions.dart';
53
import 'package:riverpod_annotation/riverpod_annotation.dart';
64
import 'package:tail_app/Backend/analytics.dart';

lib/Backend/device_registry.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class DeviceRegistry {
2121
BaseDeviceDefinition(uuid: "5fb21175-fef4-448a-a38b-c472d935abab", btName: "minitail", deviceType: DeviceType.miniTail, minVersion: Version(major: 5, minor: 0, patch: 0)),
2222
BaseDeviceDefinition(uuid: "e790f509-f95b-4eb4-b649-5b43ee1eee9c", btName: "flutter", deviceType: DeviceType.wings, minVersion: Version(major: 5, minor: 0, patch: 0)),
2323
BaseDeviceDefinition(uuid: "927dee04-ddd4-4582-8e42-69dc9fbfae66", btName: "EG2", deviceType: DeviceType.ears),
24+
BaseDeviceDefinition(uuid: "2a5d91c2-16cc-482d-acf0-5b623904f7ae", btName: "clawgear", deviceType: DeviceType.claws),
2425
BaseDeviceDefinition(uuid: "ba2f2b00-8f65-4cc3-afad-58ba1fccd62d", btName: "EarGear", deviceType: DeviceType.ears, unsupported: true),
2526
];
2627

@@ -104,9 +105,19 @@ BuiltList<BaseStatefulDevice> getAvailableGearForType(Ref ref, BuiltSet<DeviceTy
104105
}
105106

106107
@Riverpod()
107-
BuiltList<BaseStatefulDevice> getKnownGearForType(Ref ref, BuiltSet<DeviceType> deviceTypes) {
108-
final BuiltMap<String, BaseStatefulDevice> watch = KnownDevices.instance.state;
109-
return watch.values.where((element) => deviceTypes.contains(element.baseDeviceDefinition.deviceType)).toBuiltList();
108+
class GetKnownGearForType extends _$GetKnownGearForType {
109+
@override
110+
BuiltList<BaseStatefulDevice> build(BuiltSet<DeviceType> deviceTypes) {
111+
KnownDevices.instance
112+
..removeListener(_listener)
113+
..addListener(_listener);
114+
final BuiltMap<String, BaseStatefulDevice> watch = KnownDevices.instance.state;
115+
return watch.values.where((element) => deviceTypes.contains(element.baseDeviceDefinition.deviceType)).toBuiltList();
116+
}
117+
118+
void _listener() {
119+
ref.invalidateSelf();
120+
}
110121
}
111122

112123
@Riverpod(keepAlive: true)

lib/Backend/sensors.dart

Lines changed: 170 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import 'package:flutter/foundation.dart';
1010
import 'package:flutter/material.dart';
1111
import 'package:flutter_android_volume_keydown/flutter_android_volume_keydown.dart';
1212
import 'package:flutter_blue_plus/flutter_blue_plus.dart' hide CharacteristicProperties;
13-
import 'package:flutter_riverpod/flutter_riverpod.dart';
1413
import 'package:freezed_annotation/freezed_annotation.dart';
1514
import 'package:hive_ce/hive.dart';
1615
import 'package:intl/intl.dart';
@@ -422,6 +421,174 @@ class CoverTriggerDefinition extends TriggerDefinition {
422421
}
423422
}
424423

424+
class ClawTiltTriggerDefinition extends TriggerDefinition {
425+
List<StreamSubscription<String>?> rxSubscriptions = [];
426+
427+
ClawTiltTriggerDefinition(super.ref) {
428+
super.name = triggerClawTiltModeTitle;
429+
super.description = triggerClawTiltModeDescription;
430+
super.icon = const Icon(Icons.threed_rotation);
431+
super.requiredPermission = null;
432+
super.uuid = "664bd073-34cd-4c78-a7da-2b8b44fd9661";
433+
super.actionTypes = [
434+
TriggerActionDef(name: "Extend", translated: triggerClawTiltModeExtend, uuid: "74728806-c72d-4b52-94c7-f475e80b826b"),
435+
TriggerActionDef(name: "Retract", translated: triggerClawTiltModeRetract, uuid: "ca2149c2-86d2-46d7-89b9-508bfab7a29cb"),
436+
];
437+
}
438+
439+
@override
440+
Future<bool> isSupported() async {
441+
return ref.read(getKnownGearForTypeProvider(BuiltSet([DeviceType.claws]))).isNotEmpty;
442+
}
443+
444+
@override
445+
Future<void> onDisable() async {
446+
KnownDevices.instance.removeListener(onDeviceConnected);
447+
ref.read(getKnownGearForTypeProvider(BuiltSet([DeviceType.claws]))).forEach((element) {
448+
element.deviceConnectionState.removeListener(onDeviceConnected);
449+
});
450+
for (var element in rxSubscriptions) {
451+
element?.cancel();
452+
}
453+
rxSubscriptions = [];
454+
ref.read(getAvailableGearForTypeProvider(BuiltSet([DeviceType.claws]))).forEach((element) {
455+
ref
456+
.read(commandQueueProvider(element).notifier)
457+
.addCommand(BluetoothMessage(message: "STOPTILT", priority: Priority.low, responseMSG: "OK", type: CommandType.system, timestamp: DateTime.now()));
458+
});
459+
}
460+
461+
@override
462+
Future<void> onEnable() async {
463+
if (rxSubscriptions.isNotEmpty) {
464+
return;
465+
}
466+
ref.read(getAvailableGearForTypeProvider(BuiltSet([DeviceType.claws]))).forEach((element) {
467+
ref
468+
.read(commandQueueProvider(element).notifier)
469+
.addCommand(BluetoothMessage(message: "TILTMODE", responseMSG: "OK", priority: Priority.low, type: CommandType.system, timestamp: DateTime.now()));
470+
});
471+
// Disable clap trigger when this one enables
472+
ref.read(triggerListProvider).where((element) => element.triggerDefUUID == "50d65674-ed4f-4bf5-abd1-e5161faf2a5e").forEach((element) => element.enabled = false);
473+
//add listeners on new device paired
474+
KnownDevices.instance.addListener(onDeviceConnected);
475+
}
476+
477+
Future<void> onDeviceConnected() async {
478+
ref.read(getKnownGearForTypeProvider(BuiltSet([DeviceType.claws]))).map((e) {
479+
e.deviceConnectionState.removeListener(onDeviceConnected);
480+
e.deviceConnectionState.addListener(onDeviceConnected);
481+
});
482+
listen();
483+
}
484+
485+
Future<void> listen() async {
486+
//cancel old subscriptions
487+
if (rxSubscriptions.isNotEmpty) {
488+
for (var element in rxSubscriptions) {
489+
element?.cancel();
490+
}
491+
}
492+
//Store the current streams to keep them open
493+
rxSubscriptions = ref.read(getAvailableGearForTypeProvider(BuiltSet([DeviceType.claws]))).map((element) {
494+
ref
495+
.read(commandQueueProvider(element).notifier)
496+
.addCommand(BluetoothMessage(message: "TILTMODE", responseMSG: "OK", priority: Priority.low, type: CommandType.system, timestamp: DateTime.now()));
497+
//TODO: Wire up with the real commands
498+
return element.rxCharacteristicStream.listen((msg) {
499+
if (msg.contains("TILT UP")) {
500+
sendCommands("Extend", ref);
501+
}
502+
if (msg.contains("TILT DOWN")) {
503+
sendCommands("Retract", ref);
504+
}
505+
});
506+
}).toList();
507+
}
508+
}
509+
510+
class ClawClapTriggerDefinition extends TriggerDefinition {
511+
List<StreamSubscription<String>?> rxSubscriptions = [];
512+
513+
ClawClapTriggerDefinition(super.ref) {
514+
super.name = triggerClawClapModeTitle;
515+
super.description = triggerClawClapModeDescription;
516+
super.icon = const Icon(Icons.waving_hand_sharp);
517+
super.requiredPermission = null;
518+
super.uuid = "50d65674-ed4f-4bf5-abd1-e5161faf2a5e";
519+
super.actionTypes = [TriggerActionDef(name: "Clap", translated: triggerClawClapMode, uuid: "6b88bc2a-dea2-435c-88be-7c16df687225")];
520+
}
521+
522+
@override
523+
Future<bool> isSupported() async {
524+
return ref.read(getKnownGearForTypeProvider(BuiltSet([DeviceType.claws]))).isNotEmpty;
525+
}
526+
527+
@override
528+
Future<void> onDisable() async {
529+
KnownDevices.instance.removeListener(onDeviceConnected);
530+
ref.read(getKnownGearForTypeProvider(BuiltSet([DeviceType.claws]))).forEach((element) {
531+
element.deviceConnectionState.removeListener(onDeviceConnected);
532+
});
533+
for (var element in rxSubscriptions) {
534+
element?.cancel();
535+
}
536+
rxSubscriptions = [];
537+
ref.read(getAvailableGearForTypeProvider(BuiltSet([DeviceType.claws]))).forEach((element) {
538+
ref
539+
.read(commandQueueProvider(element).notifier)
540+
.addCommand(BluetoothMessage(message: "STOPCLAP", priority: Priority.low, responseMSG: "OK", type: CommandType.system, timestamp: DateTime.now()));
541+
});
542+
}
543+
544+
@override
545+
Future<void> onEnable() async {
546+
if (rxSubscriptions.isNotEmpty) {
547+
return;
548+
}
549+
ref.read(getAvailableGearForTypeProvider(BuiltSet([DeviceType.claws]))).forEach((element) {
550+
ref
551+
.read(commandQueueProvider(element).notifier)
552+
.addCommand(BluetoothMessage(message: "CLAPMODE", responseMSG: "OK", priority: Priority.low, type: CommandType.system, timestamp: DateTime.now()));
553+
});
554+
555+
// Disable claw tilt trigger when this one enables
556+
ref.read(triggerListProvider).where((element) => element.triggerDefUUID == "664bd073-34cd-4c78-a7da-2b8b44fd9661").forEach((element) => element.enabled = false);
557+
558+
//add listeners on new device paired
559+
KnownDevices.instance.addListener(onDeviceConnected);
560+
}
561+
562+
Future<void> onDeviceConnected() async {
563+
ref.read(getKnownGearForTypeProvider(BuiltSet([DeviceType.claws]))).map((e) {
564+
e.deviceConnectionState.removeListener(onDeviceConnected);
565+
e.deviceConnectionState.addListener(onDeviceConnected);
566+
});
567+
listen();
568+
}
569+
570+
Future<void> listen() async {
571+
//cancel old subscriptions
572+
if (rxSubscriptions.isNotEmpty) {
573+
for (var element in rxSubscriptions) {
574+
element?.cancel();
575+
}
576+
}
577+
//Store the current streams to keep them open
578+
rxSubscriptions = ref.read(getAvailableGearForTypeProvider(BuiltSet([DeviceType.claws]))).map((element) {
579+
ref
580+
.read(commandQueueProvider(element).notifier)
581+
.addCommand(BluetoothMessage(message: "CLAPMODE", responseMSG: "OK", priority: Priority.low, type: CommandType.system, timestamp: DateTime.now()));
582+
return element.rxCharacteristicStream.listen((msg) {
583+
if (msg.contains("DOUBLE CLAP")) {
584+
// we don't store the actions in class as multiple Triggers can exist, so go get them. This is only necessary when the action is dependent on gear being available
585+
sendCommands("Clap", ref);
586+
}
587+
});
588+
}).toList();
589+
}
590+
}
591+
425592
class EarMicTriggerDefinition extends TriggerDefinition {
426593
List<StreamSubscription<String>?> rxSubscriptions = [];
427594

@@ -888,6 +1055,8 @@ class TriggerDefinitionList extends _$TriggerDefinitionList {
8881055
EarTiltTriggerDefinition(ref),
8891056
RandomTriggerDefinition(ref),
8901057
VolumeButtonTriggerDefinition(ref),
1058+
ClawClapTriggerDefinition(ref),
1059+
ClawTiltTriggerDefinition(ref),
8911060
];
8921061

8931062
triggerDefinitions.sort();

lib/Frontend/Widgets/device_type_widget.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ class DeviceTypeWidget extends ConsumerWidget {
3030
clearable: false,
3131
value: selected,
3232
onChanged: onSelectionChanged,
33-
itemCount: DeviceType.values.length,
33+
itemCount: DeviceType.values.where((element) => !element.isHidden()).length,
3434
itemBuilder: (state, i) {
35-
DeviceType deviceType = DeviceType.values[i];
35+
DeviceType deviceType = DeviceType.values.where((element) => !element.isHidden()).toList()[i];
3636
return ChoiceChip(
3737
selectedColor: deviceType.color(),
3838
selected: state.selected(deviceType),

lib/Frontend/Widgets/scan_for_new_device.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class _ScanForNewDevice extends ConsumerState<ScanForNewDevice> {
7373
}
7474
int code = Random().nextInt(899999) + 100000;
7575
baseStoredDevice.conModePin = code.toString();
76-
if (KnownDevices.instance.state.containsKey(baseStoredDevice.btMACAddress)) {
76+
if (!KnownDevices.instance.state.containsKey(baseStoredDevice.btMACAddress)) {
7777
KnownDevices.instance.add(statefulDevice);
7878
}
7979
context.pop();

0 commit comments

Comments
 (0)