Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -668,5 +668,11 @@
"saw" : "Saw",
"comingSoon": "Coming Soon",
"startRecording": "Start Recording",
"stopRecording": "Stop Recording"
"stopRecording": "Stop Recording",
"changeHardware": "Change Hardware",
"psLab": "PSLab",
"psLabBoard": "PSLab Board",
"internalSensors": "Internal sensors",
"selectHardware": "Select Hardware",
"selectHardwareQuestion": "What hardware do you want to use?"
}
18 changes: 14 additions & 4 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import 'package:pslab/view/multimeter_screen.dart';
import 'package:pslab/view/oscilloscope_screen.dart';
import 'package:pslab/view/power_source_screen.dart';
import 'package:pslab/view/robotic_arm_screen.dart';
import 'package:pslab/view/select_hardware.dart';
import 'package:pslab/view/sensors_screen.dart';
import 'package:pslab/view/settings_screen.dart';
import 'package:pslab/view/about_us_screen.dart';
Expand All @@ -30,9 +31,16 @@ import 'package:pslab/view/wave_generator_screen.dart';
import 'package:pslab/view/experiments_screen.dart';
import 'constants.dart';

void main() {
void main() async {
setupLocator();
WidgetsFlutterBinding.ensureInitialized();
final boardProvider = getIt<BoardStateProvider>();
await boardProvider.loadSavedHardware();
String initialRoute = '/selectHardware';
if (boardProvider.selectedHardware.isNotEmpty) {
initialRoute = '/';
}

runApp(
MultiProvider(
providers: [
Expand All @@ -46,13 +54,14 @@ void main() {
create: (context) => getIt<SHT21Provider>(),
),
],
child: const MyApp(),
child: MyApp(initialRoute: initialRoute),
),
);
}

class MyApp extends StatelessWidget {
const MyApp({super.key});
const MyApp({super.key, required this.initialRoute});
final String initialRoute;

@override
Widget build(BuildContext context) {
Expand All @@ -77,8 +86,9 @@ class MyApp extends StatelessWidget {
),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
initialRoute: '/',
initialRoute: initialRoute,
routes: {
'/selectHardware': (context) => const HardwareSelectionScreen(),
'/': (context) => const InstrumentsScreen(),
'/oscilloscope': (context) => const OscilloscopeScreen(),
'/multimeter': (context) => const MultimeterScreen(),
Expand Down
18 changes: 17 additions & 1 deletion lib/providers/board_state_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import 'package:pslab/others/logger_service.dart';
import 'package:pslab/providers/locator.dart';
import 'package:pslab/providers/settings_config_provider.dart';
import 'package:usb_serial/usb_serial.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'package:pslab/others/science_lab_common.dart';

class BoardStateProvider extends ChangeNotifier {
late SettingsConfigProvider configProvider;
AppLocalizations appLocalizations = getIt.get<AppLocalizations>();
AppLocalizations get appLocalizations => getIt.get<AppLocalizations>();
bool initialisationStatus = false;
bool pslabIsConnected = false;
bool hasPermission = false;
Expand All @@ -23,6 +24,8 @@ class BoardStateProvider extends ChangeNotifier {
int pslabVersion = 0;
int pslabFirmwareVersion = 0;
bool _isProcessing = false;
String _selectedHardware = "";
String get selectedHardware => _selectedHardware;

final ValueNotifier<String?> legacyFirmwareNotifier = ValueNotifier(null);

Expand Down Expand Up @@ -120,4 +123,17 @@ class BoardStateProvider extends ChangeNotifier {
}
return false;
}

Future<void> loadSavedHardware() async {
final prefs = await SharedPreferences.getInstance();
_selectedHardware = prefs.getString('selected_hardware') ?? "";
notifyListeners();
}

Future<void> setHardware(String name) async {
_selectedHardware = name;
final prefs = await SharedPreferences.getInstance();
await prefs.setString('selected_hardware', name);
notifyListeners();
}
}
88 changes: 64 additions & 24 deletions lib/view/instruments_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ class _InstrumentData {
final String heading;
final String description;
final String name;
final List<String> supportedHardware;

_InstrumentData(this.heading, this.description, this.name);
_InstrumentData(
this.heading, this.description, this.name, this.supportedHardware);
}

class _InstrumentsScreenState extends State<InstrumentsScreen> {
List<int> _filteredIndices = <int>[];
AppLocalizations appLocalizations = getIt.get<AppLocalizations>();
late List<_InstrumentData> _instrumentDatas;
List<_InstrumentData> _instrumentDatas = [];

void _onItemTapped(int index) {
_InstrumentData instrument = _instrumentDatas[index];
Expand Down Expand Up @@ -57,6 +59,18 @@ class _InstrumentsScreenState extends State<InstrumentsScreen> {
});
}

void _updateVisibleInstruments() {
final currentHardware = getIt.get<BoardStateProvider>().selectedHardware;

setState(() {
_filteredIndices =
List.generate(_instrumentDatas.length, (i) => i).where((i) {
final instrument = _instrumentDatas[i];
return instrument.supportedHardware.contains(currentHardware);
}).toList();
});
}

@override
void initState() {
super.initState();
Expand Down Expand Up @@ -87,37 +101,61 @@ class _InstrumentsScreenState extends State<InstrumentsScreen> {
});

_instrumentDatas = [
_InstrumentData(appLocalizations.oscilloscope,
appLocalizations.oscilloscopeDesc, '/oscilloscope'),
_InstrumentData(
appLocalizations.oscilloscope,
appLocalizations.oscilloscopeDesc,
'/oscilloscope',
['pslab_board', 'internal_sensors']),
_InstrumentData(appLocalizations.multimeter,
appLocalizations.multimeterDesc, '/multimeter'),
_InstrumentData(appLocalizations.logicAnalyzer,
appLocalizations.logicAnalyzerDesc, '/logicAnalyzer'),
appLocalizations.multimeterDesc, '/multimeter', ['pslab_board']),
_InstrumentData(
appLocalizations.sensors, appLocalizations.sensorsDesc, '/sensors'),
_InstrumentData(appLocalizations.waveGenerator,
appLocalizations.waveGeneratorDesc, '/waveGenerator'),
appLocalizations.logicAnalyzer,
appLocalizations.logicAnalyzerDesc,
'/logicAnalyzer',
['pslab_board']),
_InstrumentData(appLocalizations.sensors, appLocalizations.sensorsDesc,
'/sensors', ['pslab_board']),
_InstrumentData(
appLocalizations.waveGenerator,
appLocalizations.waveGeneratorDesc,
'/waveGenerator',
['pslab_board', 'internal_sensors']),
_InstrumentData(appLocalizations.powerSource,
appLocalizations.powerSourceDesc, '/powerSource'),
appLocalizations.powerSourceDesc, '/powerSource', ['pslab_board']),
_InstrumentData(appLocalizations.luxMeter, appLocalizations.luxMeterDesc,
'/luxmeter'),
_InstrumentData(appLocalizations.accelerometer,
appLocalizations.accelerometerDesc, '/accelerometer'),
_InstrumentData(appLocalizations.barometer,
appLocalizations.barometerDesc, '/barometer'),
'/luxmeter', ['pslab_board', 'internal_sensors']),
_InstrumentData(
appLocalizations.accelerometer,
appLocalizations.accelerometerDesc,
'/accelerometer',
['pslab_board', 'internal_sensors']),
_InstrumentData(
appLocalizations.barometer,
appLocalizations.barometerDesc,
'/barometer',
['pslab_board', 'internal_sensors']),
_InstrumentData(appLocalizations.compass, appLocalizations.compassDesc,
'/compass', ['pslab_board', 'internal_sensors']),
_InstrumentData(
appLocalizations.compass, appLocalizations.compassDesc, '/compass'),
_InstrumentData(appLocalizations.gyroscope,
appLocalizations.gyroscopeDesc, '/gyroscope'),
_InstrumentData(appLocalizations.thermometer,
appLocalizations.thermometerDesc, '/thermometer'),
appLocalizations.gyroscope,
appLocalizations.gyroscopeDesc,
'/gyroscope',
['pslab_board', 'internal_sensors']),
_InstrumentData(
appLocalizations.thermometer,
appLocalizations.thermometerDesc,
'/thermometer',
['pslab_board', 'internal_sensors']),
_InstrumentData(appLocalizations.roboticArm,
appLocalizations.roboticArmDesc, '/roboticArm'),
appLocalizations.roboticArmDesc, '/roboticArm', ['pslab_board']),
// Instruments below are not yet implemented.
//_InstrumentData(appLocalizations.gasSensor, appLocalizations.gasSensorDesc, '/gassensor'),
//_InstrumentData(appLocalizations.dustSensor, appLocalizations.dustSensorDesc, '/dustsensor'),
_InstrumentData(appLocalizations.soundMeter,
appLocalizations.soundMeterDesc, '/soundmeter'),
_InstrumentData(
appLocalizations.soundMeter,
appLocalizations.soundMeterDesc,
'/soundmeter',
['pslab_board', 'internal_sensors']),
];

_filteredIndices =
Expand All @@ -126,6 +164,8 @@ class _InstrumentsScreenState extends State<InstrumentsScreen> {
_setPortraitOrientation();
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
});

_updateVisibleInstruments();
}

void _setPortraitOrientation() {
Expand Down
106 changes: 106 additions & 0 deletions lib/view/select_hardware.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import 'package:flutter/material.dart';
import 'package:pslab/l10n/app_localizations.dart';
import 'package:pslab/providers/locator.dart';
import 'package:pslab/providers/board_state_provider.dart';
import 'package:pslab/view/widgets/main_scaffold_widget.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../theme/colors.dart';

class HardwareSelectionScreen extends StatefulWidget {
const HardwareSelectionScreen({super.key});

@override
State<HardwareSelectionScreen> createState() =>
_HardwareSelectionScreenState();
}

class _HardwareOption {
final String label;
final IconData icon;
final String value;

_HardwareOption(this.label, this.icon, this.value);
}

class _HardwareSelectionScreenState extends State<HardwareSelectionScreen> {
final AppLocalizations appLocalizations = getIt.get<AppLocalizations>();
late List<_HardwareOption> _options;

@override
void initState() {
super.initState();
_options = [
_HardwareOption(appLocalizations.psLabBoard, Icons.usb, "pslab_board"),
_HardwareOption(appLocalizations.internalSensors, Icons.developer_board,
"internal_sensors"),
];
}

Future<void> _selectHardware(String hardwareValue) async {
final boardProvider = getIt.get<BoardStateProvider>();
boardProvider.setHardware(hardwareValue);

final prefs = await SharedPreferences.getInstance();
await prefs.setString('selected_hardware', hardwareValue);

if (mounted) {
Navigator.pushReplacementNamed(context, '/');
}
}

@override
Widget build(BuildContext context) {
return MainScaffold(
index: 1,
title: appLocalizations.selectHardware,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Center(
child: Image.asset(
'assets/icons/icon.png',
height: 100,
fit: BoxFit.contain,
),
),
const SizedBox(height: 40),
Text(
appLocalizations.selectHardwareQuestion,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 32),
..._options.map((option) => Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 20),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12)),
backgroundColor: primaryRed,
),
onPressed: () => _selectHardware(option.value),
icon: Icon(
option.icon,
size: 28,
color: chartTextColor,
),
label: Text(option.label,
style:
TextStyle(fontSize: 18, color: chartTextColor)),
),
)),
],
),
),
),
);
}
}
Loading
Loading