diff --git a/lib/colors.dart b/lib/colors.dart new file mode 100644 index 000000000..efaff7395 --- /dev/null +++ b/lib/colors.dart @@ -0,0 +1,3 @@ +import 'dart:ui'; + +Color primaryRed = const Color(0xFFD32F2F); diff --git a/lib/constants.dart b/lib/constants.dart index 917caec31..2436083c6 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -101,6 +101,14 @@ String wifi = 'WIFI'; String whatisPslab = 'What is PSLab Device?'; String pslabUrl = 'https://pslab.io'; +String settings = 'Settings'; +String start = 'Auto Start'; +String autoStartText = 'Auto start app when PSLab device is connected'; +String export = 'Export Data Format'; +String txtFormat = 'TXT Format'; +String csvFormat = 'CSV Format'; +String cancel = 'CANCEL'; +String currentFormat = 'Current format is '; String aboutUs = 'About Us'; String pslabDescription = 'The goal of PSLab is to create an Open Source hardware device (open on all layers) that can be used for experiments by teachers, students and citizen scientists. Our tiny pocket lab provides an array of sensors for doing science and engineering experiments. It provides functions of numerous measurement devices including an oscilloscope, a waveform generator, a frequency generator, a frequency counter, a programmable voltage, current source and as a data logger.'; diff --git a/lib/main.dart b/lib/main.dart index 09be5b76f..960139356 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:pslab/view/connect_device_screen.dart'; import 'package:pslab/view/faq_screen.dart'; import 'package:pslab/view/instruments_screen.dart'; import 'package:pslab/view/oscilloscope_screen.dart'; +import 'package:pslab/view/settings_screen.dart'; import 'package:pslab/view/about_us_screen.dart'; import 'constants.dart'; @@ -44,6 +45,7 @@ class MyApp extends StatelessWidget { '/oscilloscope': (context) => const OscilloscopeScreen(), '/connectDevice': (context) => const ConnectDeviceScreen(), '/faq': (context) => const FAQScreen(), + '/settings': (context) => const SettingsScreen(), '/aboutUs': (context) => const AboutUsScreen(), }, ); diff --git a/lib/providers/board_state_provider.dart b/lib/providers/board_state_provider.dart index 3ace11b21..836e710e4 100644 --- a/lib/providers/board_state_provider.dart +++ b/lib/providers/board_state_provider.dart @@ -1,5 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:pslab/communication/science_lab.dart'; +import 'package:pslab/constants.dart'; import 'package:pslab/others/logger_service.dart'; import 'package:pslab/providers/locator.dart'; import 'package:usb_serial/usb_serial.dart'; @@ -12,6 +13,8 @@ class BoardStateProvider extends ChangeNotifier { bool hasPermission = false; late ScienceLabCommon scienceLabCommon; String pslabVersionID = 'Not Connected'; + String exportFormat = txtFormat; + bool autoStart = true; BoardStateProvider() { scienceLabCommon = getIt.get(); @@ -21,21 +24,23 @@ class BoardStateProvider extends ChangeNotifier { await scienceLabCommon.initialize(); pslabIsConnected = await scienceLabCommon.openDevice(); setPSLabVersionIDs(); - UsbSerial.usbEventStream?.listen( - (UsbEvent usbEvent) async { - if (usbEvent.event == UsbEvent.ACTION_USB_ATTACHED) { - if (await attemptToConnectPSLab()) { - pslabIsConnected = await scienceLabCommon.openDevice(); - setPSLabVersionIDs(); + if (autoStart) { + UsbSerial.usbEventStream?.listen( + (UsbEvent usbEvent) async { + if (usbEvent.event == UsbEvent.ACTION_USB_ATTACHED) { + if (await attemptToConnectPSLab()) { + pslabIsConnected = await scienceLabCommon.openDevice(); + setPSLabVersionIDs(); + } + } else if (usbEvent.event == UsbEvent.ACTION_USB_DETACHED) { + scienceLabCommon.setConnected(false); + pslabIsConnected = false; + pslabVersionID = 'Not Connected'; + notifyListeners(); } - } else if (usbEvent.event == UsbEvent.ACTION_USB_DETACHED) { - scienceLabCommon.setConnected(false); - pslabIsConnected = false; - pslabVersionID = 'Not Connected'; - notifyListeners(); - } - }, - ); + }, + ); + } } Future setPSLabVersionIDs() async { diff --git a/lib/view/settings_screen.dart b/lib/view/settings_screen.dart new file mode 100644 index 000000000..098cf2a37 --- /dev/null +++ b/lib/view/settings_screen.dart @@ -0,0 +1,123 @@ +import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; +import 'package:pslab/colors.dart'; +import 'package:pslab/providers/board_state_provider.dart'; +import 'package:pslab/view/widgets/main_scaffold_widget.dart'; +import 'package:pslab/constants.dart'; + +class SettingsScreen extends StatefulWidget { + const SettingsScreen({super.key}); + + @override + State createState() => _SettingsScreenState(); +} + +class _SettingsScreenState extends State { + bool isTxtFormatSelected = + (GetIt.instance.get().exportFormat == txtFormat); + bool isCsvFormatSelected = + (GetIt.instance.get().exportFormat == csvFormat); + + void _showExportFormatDialog() { + showDialog( + context: context, + builder: (BuildContext context) { + return SimpleDialog( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.zero, + ), + backgroundColor: Colors.white, + title: Text(export, + style: + const TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + children: [ + RadioListTile( + title: Text(txtFormat), + value: true, + groupValue: isTxtFormatSelected, + activeColor: primaryRed, + onChanged: (bool? value) { + setState( + () { + isTxtFormatSelected = true; + isCsvFormatSelected = false; + GetIt.instance.get().exportFormat = + txtFormat; + Navigator.of(context).pop(); + }, + ); + }, + ), + RadioListTile( + title: Text(csvFormat), + value: true, + groupValue: isCsvFormatSelected, + activeColor: primaryRed, + onChanged: (bool? value) { + setState( + () { + isTxtFormatSelected = false; + isCsvFormatSelected = true; + GetIt.instance.get().exportFormat = + csvFormat; + Navigator.of(context).pop(); + }, + ); + }, + ), + Align( + alignment: Alignment.bottomRight, + child: GestureDetector( + onTap: () { + Navigator.of(context).pop(); + }, + child: Padding( + padding: const EdgeInsets.only(right: 20, bottom: 5), + child: Text( + cancel, + style: const TextStyle(fontWeight: FontWeight.w500), + ), + ), + ), + ) + ], + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return MainScaffold( + title: settings, + index: 4, + body: SafeArea( + child: ListView( + children: [ + const SizedBox(height: 10), + CheckboxListTile( + title: Text(start), + subtitle: Text(autoStartText), + value: GetIt.instance.get().autoStart, + onChanged: (bool? value) { + setState(() { + GetIt.instance.get().autoStart = value!; + }); + }, + activeColor: primaryRed, + ), + const SizedBox(height: 10), + ListTile( + title: Text(export), + subtitle: Text(currentFormat + + GetIt.instance.get().exportFormat), + onTap: () { + _showExportFormatDialog(); + }, + ), + ], + ), + ), + ); + } +} diff --git a/lib/view/widgets/navigation_drawer.dart b/lib/view/widgets/navigation_drawer.dart index 079fca8fd..62564b42c 100644 --- a/lib/view/widgets/navigation_drawer.dart +++ b/lib/view/widgets/navigation_drawer.dart @@ -171,7 +171,16 @@ class _NavDrawerState extends State { ), ), onTap: () { - /**/ + if (Navigator.canPop(context) && + ModalRoute.of(context)?.settings.name == '/settings') { + Navigator.popUntil(context, ModalRoute.withName('/settings')); + } else { + Navigator.pushNamedAndRemoveUntil( + context, + '/settings', + (route) => route.isFirst, + ); + } }, ), const Divider(),