diff --git a/lib/screens/level_selection.dart b/lib/screens/level_selection.dart index eff9274..41eb4f7 100644 --- a/lib/screens/level_selection.dart +++ b/lib/screens/level_selection.dart @@ -1,14 +1,13 @@ import 'dart:io'; -import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; -import 'package:sense_the_rhythm/widgets/connection_status_button.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:file_picker/file_picker.dart'; import 'package:sense_the_rhythm/utils/esense_input.dart'; import 'package:sense_the_rhythm/utils/simfile.dart'; -import 'package:sense_the_rhythm/widgets/esense_connect_dialog.dart'; -import 'package:sense_the_rhythm/screens/level.dart'; +import 'package:sense_the_rhythm/widgets/connection_status_button.dart'; +import 'package:sense_the_rhythm/widgets/level_list_entry.dart'; class LevelSelection extends StatefulWidget { const LevelSelection({super.key}); @@ -133,17 +132,7 @@ class _LevelSelectionState extends State { const Divider(), itemBuilder: (context, index) { Simfile simfile = stepmaniaCoursesFoldersFiltered[index]; - return ListTile( - leading: Image.file(File(simfile.bannerPath!)), - trailing: Icon(Icons.play_arrow), - title: Text(simfile.tags["TITLE"]!), - subtitle: Text('3:45'), - onTap: () => Navigator.push( - context, - MaterialPageRoute( - builder: (BuildContext context) => - Level(simfile))), - ); + return LevelListEntry(simfile: simfile); }, ), ), diff --git a/lib/utils/esense_input.dart b/lib/utils/esense_input.dart index d909c0d..4edb983 100644 --- a/lib/utils/esense_input.dart +++ b/lib/utils/esense_input.dart @@ -11,7 +11,7 @@ class ESenseInput { static final instance = ESenseInput._(); ESenseManager eSenseManager = ESenseManager('unknown'); - ValueNotifier deviceStatus = ValueNotifier(''); + ValueNotifier deviceStatus = ValueNotifier('Disconnected'); StreamSubscription? subscription; String eSenseDeviceName = ''; @@ -58,23 +58,23 @@ class ESenseInput { connected = false; switch (event.type) { case ConnectionType.connected: - deviceStatus.value = 'connected'; + deviceStatus.value = 'Connected'; connected = true; _startListenToSensorEvents(); break; case ConnectionType.unknown: - deviceStatus.value = 'unknown'; + deviceStatus.value = 'Unknown'; break; case ConnectionType.disconnected: - deviceStatus.value = 'disconnected'; + deviceStatus.value = 'Disconnected'; sampling = false; _pauseListenToSensorEvents(); break; case ConnectionType.device_found: - deviceStatus.value = 'device_found'; + deviceStatus.value = 'Device_found'; break; case ConnectionType.device_not_found: - deviceStatus.value = 'device_not_found'; + deviceStatus.value = 'Device_not_found'; break; } }); @@ -155,11 +155,11 @@ class ESenseInput { print('Trying to connect to eSense device namend \'$deviceName\''); eSenseDeviceName = deviceName; eSenseManager.deviceName = deviceName; - connected = await eSenseManager.connect(); + bool connecting = await eSenseManager.connect(); print( 'Trying to connect to eSense device namend \'${eSenseManager.deviceName}\''); - deviceStatus.value = connected ? 'connecting...' : 'connection failed'; + deviceStatus.value = connecting ? 'connecting...' : 'connection failed'; print(deviceStatus.value); } } diff --git a/lib/widgets/esense_not_connected_dialog.dart b/lib/widgets/esense_not_connected_dialog.dart new file mode 100644 index 0000000..32d1d6b --- /dev/null +++ b/lib/widgets/esense_not_connected_dialog.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +class ESenseNotConnectedDialog extends StatelessWidget { + const ESenseNotConnectedDialog( + {super.key, required this.onCancel, required this.onContinue}); + + final VoidCallback onCancel; + final VoidCallback onContinue; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text("ESense not connected"), + content: const Text( + "You will only be able to play with the arrow keys of an external keyboard. "), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context, 'Cancel'); + onCancel(); + }, + child: const Text('Connect to ESense'), + ), + TextButton( + onPressed: () { + Navigator.pop(context, 'Cancel'); + onContinue(); + }, + child: const Text('Continue anyway'), + ), + ], + ); + } +} diff --git a/lib/widgets/level_list_entry.dart b/lib/widgets/level_list_entry.dart new file mode 100644 index 0000000..a47a9c2 --- /dev/null +++ b/lib/widgets/level_list_entry.dart @@ -0,0 +1,68 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:sense_the_rhythm/utils/esense_input.dart'; +import 'package:sense_the_rhythm/utils/simfile.dart'; +import 'package:sense_the_rhythm/screens/level.dart'; +import 'package:sense_the_rhythm/widgets/esense_connect_dialog.dart'; +import 'package:sense_the_rhythm/widgets/esense_not_connected_dialog.dart'; + +class LevelListEntry extends StatelessWidget { + const LevelListEntry({ + super.key, + required this.simfile, + }); + + final Simfile simfile; + + void navigateToLevel(BuildContext context) { + Navigator.push(context, + MaterialPageRoute(builder: (BuildContext context) => Level(simfile))); + } + + void openESenseConnectDialog(context) { + showDialog( + context: context, + builder: (BuildContext context) { + return ESenseConnectDialog( + deviceStatus: ESenseInput.instance.deviceStatus, + connect: (String name) { + ESenseInput.instance.connectToESense(name); + }); + }, + ); + } + + void tapHandler(BuildContext context) { + if (ESenseInput.instance.connected) { + navigateToLevel(context); + } else { + showDialog( + context: context, + builder: (BuildContext context) { + return ESenseNotConnectedDialog( + onCancel: () { + openESenseConnectDialog(context); + }, + onContinue: () { + navigateToLevel(context); + }, + ); + }, + ); + } + } + + @override + Widget build(BuildContext context) { + return ListTile( + leading: Image.file(File(simfile.bannerPath!)), + trailing: Icon(Icons.play_arrow), + title: Text(simfile.tags["TITLE"]!), + subtitle: Text('3:45'), + onTap: () { + tapHandler(context); + }, + ); + } +}