Skip to content

Commit e499cd6

Browse files
fix: added snackbar and small ui changes in lux meter. (#2747)
Co-authored-by: Padmal <[email protected]>
1 parent 681ca7c commit e499cd6

File tree

4 files changed

+161
-93
lines changed

4 files changed

+161
-93
lines changed

lib/constants.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,10 @@ String soundMeterError = 'Sound sensor error:';
260260
String soundMeterInitialError = 'Sound sensor initialization error:';
261261
String db = 'dB';
262262
String soundMeterTitle = 'Sound Meter';
263+
String noLightSensor = "Device does not have a light sensor";
264+
String lightSensorErrorDetails = "Light sensor error details:";
265+
String lightSensorErrorLog =
266+
"No light sensor data received - sensor may not be available";
263267
String playBackSummary = 'Playback Summary';
264268
String servo = 'Servo:';
265269
String percentage = '%';

lib/providers/luxmeter_state_provider.dart

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'dart:async';
22
import 'dart:math';
33
import 'package:fl_chart/fl_chart.dart';
4-
import 'package:flutter/material.dart';
54
import 'package:pslab/others/logger_service.dart';
65
import 'package:light/light.dart';
76
import 'package:flutter/foundation.dart';
@@ -22,7 +21,13 @@ class LuxMeterStateProvider extends ChangeNotifier {
2221
double _luxMax = 0;
2322
double _luxSum = 0;
2423
int _dataCount = 0;
25-
void initializeSensors() {
24+
bool _sensorAvailable = false;
25+
26+
Function(String)? onSensorError;
27+
28+
void initializeSensors({Function(String)? onError}) {
29+
onSensorError = onError;
30+
2631
try {
2732
_light = Light();
2833
_startTime = DateTime.now().millisecondsSinceEpoch / 1000.0;
@@ -32,23 +37,41 @@ class LuxMeterStateProvider extends ChangeNotifier {
3237
_updateData();
3338
notifyListeners();
3439
});
40+
41+
Timer sensorTimeout = Timer(const Duration(seconds: 3), () {
42+
if (!_sensorAvailable) {
43+
_handleSensorError(lightSensorErrorLog);
44+
}
45+
});
46+
3547
_lightSubscription = _light!.lightSensorStream.listen(
3648
(int luxValue) {
3749
_currentLux = luxValue.toDouble();
50+
if (!_sensorAvailable) {
51+
_sensorAvailable = true;
52+
sensorTimeout.cancel();
53+
}
3854
notifyListeners();
3955
},
4056
onError: (error) {
41-
logger.e(
42-
"$lightSensorError $error",
43-
);
57+
logger.e("$lightSensorError $error");
58+
sensorTimeout.cancel();
59+
_handleSensorError(error);
4460
},
45-
cancelOnError: true,
61+
cancelOnError: false,
4662
);
4763
} catch (e) {
4864
logger.e("$lightSensorInitialError $e");
65+
_handleSensorError(e);
4966
}
5067
}
5168

69+
void _handleSensorError(dynamic error) {
70+
_sensorAvailable = false;
71+
onSensorError?.call(noLightSensor);
72+
logger.e("$lightSensorErrorDetails $error");
73+
}
74+
5275
void disposeSensors() {
5376
_lightSubscription?.cancel();
5477
_timeTimer?.cancel();
@@ -61,6 +84,8 @@ class LuxMeterStateProvider extends ChangeNotifier {
6184
}
6285

6386
void _updateData() {
87+
if (!_sensorAvailable) return;
88+
6489
final lux = _currentLux;
6590
final time = _currentTime;
6691
_luxData.add(lux);

lib/theme/colors.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ Color selectedMenuColor = Colors.red;
4040
Color menuColor = Colors.grey;
4141
Color listTileFocusColor = Colors.grey[350]!;
4242
Color oscilloscopeOptionLabelColor = Colors.black;
43+
Color snackBarBackgroundColor = Colors.grey[700]!;
44+
Color snackBarContentColor = Colors.white;
4345
Color guideDrawerBackgroundColor = Colors.white;
4446
Color guideDrawerHeadingColor = Colors.black87;
4547
Color guideDrawerHighlightColor = Colors.black54;

lib/view/luxmeter_screen.dart

Lines changed: 124 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
22
import 'package:provider/provider.dart';
33
import 'package:pslab/constants.dart';
44
import 'package:pslab/providers/luxmeter_state_provider.dart';
5-
import 'package:pslab/view/widgets/guide_widget.dart';
65
import 'package:pslab/view/widgets/common_scaffold_widget.dart';
6+
import 'package:pslab/view/widgets/guide_widget.dart';
77
import 'package:pslab/view/widgets/luxmeter_card.dart';
88
import 'package:fl_chart/fl_chart.dart';
99

@@ -16,6 +16,7 @@ class LuxMeterScreen extends StatefulWidget {
1616
}
1717

1818
class _LuxMeterScreenState extends State<LuxMeterScreen> {
19+
late LuxMeterStateProvider _provider;
1920
bool _showGuide = false;
2021
static const imagePath = 'assets/images/bh1750_schematic.png';
2122
void _showInstrumentGuide() {
@@ -49,13 +50,43 @@ class _LuxMeterScreenState extends State<LuxMeterScreen> {
4950
}
5051

5152
@override
52-
Widget build(BuildContext context) {
53-
return MultiProvider(
54-
providers: [
55-
ChangeNotifierProvider<LuxMeterStateProvider>(
56-
create: (_) => LuxMeterStateProvider()..initializeSensors(),
53+
void initState() {
54+
super.initState();
55+
_provider = LuxMeterStateProvider();
56+
WidgetsBinding.instance.addPostFrameCallback((_) {
57+
if (mounted) {
58+
_provider.initializeSensors(onError: _showSensorErrorSnackbar);
59+
}
60+
});
61+
}
62+
63+
@override
64+
void dispose() {
65+
_provider.disposeSensors();
66+
_provider.dispose();
67+
super.dispose();
68+
}
69+
70+
void _showSensorErrorSnackbar(String message) {
71+
if (mounted) {
72+
ScaffoldMessenger.of(context).showSnackBar(
73+
SnackBar(
74+
content: Text(
75+
message,
76+
style: TextStyle(color: snackBarContentColor),
77+
),
78+
backgroundColor: snackBarBackgroundColor,
79+
duration: const Duration(seconds: 4),
80+
behavior: SnackBarBehavior.floating,
5781
),
58-
],
82+
);
83+
}
84+
}
85+
86+
@override
87+
Widget build(BuildContext context) {
88+
return ChangeNotifierProvider<LuxMeterStateProvider>.value(
89+
value: _provider,
5990
child: Stack(children: [
6091
CommonScaffold(
6192
title: luxMeterTitle,
@@ -90,6 +121,7 @@ class _LuxMeterScreenState extends State<LuxMeterScreen> {
90121
builder: (context, provider, child) {
91122
final screenWidth = MediaQuery.of(context).size.width;
92123
final cardMargin = screenWidth < 400 ? 8.0 : 16.0;
124+
final cardPadding = screenWidth < 400 ? 2.0 : 5.0;
93125
List<FlSpot> spots = provider.getLuxChartData();
94126
double maxLux = provider.getMaxLux();
95127
double maxTime = provider.getMaxTime();
@@ -98,10 +130,10 @@ class _LuxMeterScreenState extends State<LuxMeterScreen> {
98130

99131
return Container(
100132
margin: EdgeInsets.fromLTRB(cardMargin, 0, cardMargin, cardMargin),
101-
padding: EdgeInsets.all(cardMargin),
133+
padding: EdgeInsets.all(cardPadding),
102134
decoration: BoxDecoration(
103135
color: chartBackgroundColor,
104-
borderRadius: BorderRadius.circular(8),
136+
borderRadius: BorderRadius.zero,
105137
),
106138
child: _buildChart(
107139
screenWidth, maxLux, maxTime, minTime, timeInterval, spots),
@@ -152,97 +184,102 @@ class _LuxMeterScreenState extends State<LuxMeterScreen> {
152184
: 10.0;
153185
final axisNameFontSize = screenWidth < 400 ? 9.0 : 10.0;
154186
final reservedSizeBottom = screenWidth < 400 ? 25.0 : 30.0;
155-
final reservedSizeLeft = screenWidth < 400 ? 20.0 : 25.0;
156-
return LineChart(
157-
LineChartData(
158-
backgroundColor: chartBackgroundColor,
159-
titlesData: FlTitlesData(
160-
show: true,
161-
topTitles: AxisTitles(
162-
axisNameWidget: Padding(
163-
padding: EdgeInsets.only(left: screenWidth < 400 ? 15 : 25),
164-
child: Text(
165-
timeAxisLabel,
187+
final reservedSizeLeft = screenWidth < 400 ? 27.0 : 30.0;
188+
final reservedSizeRight = screenWidth < 400 ? 27.0 : 30.0;
189+
return Padding(
190+
padding: const EdgeInsets.only(right: 20.0),
191+
child: LineChart(
192+
LineChartData(
193+
backgroundColor: chartBackgroundColor,
194+
titlesData: FlTitlesData(
195+
show: true,
196+
topTitles: AxisTitles(
197+
axisNameWidget: Padding(
198+
padding: EdgeInsets.only(left: screenWidth < 400 ? 15 : 25),
199+
child: Text(
200+
timeAxisLabel,
201+
style: TextStyle(
202+
fontSize: axisNameFontSize,
203+
color: chartTextColor,
204+
fontWeight: FontWeight.bold,
205+
),
206+
),
207+
),
208+
axisNameSize: screenWidth < 400 ? 18 : 20,
209+
),
210+
bottomTitles: AxisTitles(
211+
sideTitles: SideTitles(
212+
showTitles: true,
213+
reservedSize: reservedSizeBottom,
214+
getTitlesWidget: sideTitleWidgets,
215+
interval: timeInterval,
216+
),
217+
),
218+
leftTitles: AxisTitles(
219+
axisNameWidget: Text(
220+
lx,
166221
style: TextStyle(
167222
fontSize: axisNameFontSize,
168223
color: chartTextColor,
169224
fontWeight: FontWeight.bold,
170225
),
171226
),
172-
),
173-
axisNameSize: screenWidth < 400 ? 18 : 20,
174-
),
175-
bottomTitles: AxisTitles(
176-
sideTitles: SideTitles(
177-
showTitles: true,
178-
reservedSize: reservedSizeBottom,
179-
getTitlesWidget: sideTitleWidgets,
180-
interval: timeInterval,
181-
),
182-
),
183-
leftTitles: AxisTitles(
184-
axisNameWidget: Text(
185-
lx,
186-
style: TextStyle(
187-
fontSize: axisNameFontSize,
188-
color: chartTextColor,
189-
fontWeight: FontWeight.bold,
227+
sideTitles: SideTitles(
228+
reservedSize: reservedSizeLeft,
229+
showTitles: true,
230+
getTitlesWidget: (value, meta) {
231+
return SideTitleWidget(
232+
meta: meta,
233+
child: Text(
234+
value.toInt().toString(),
235+
style: TextStyle(
236+
color: chartTextColor,
237+
fontSize: chartFontSize,
238+
),
239+
),
240+
);
241+
},
242+
interval: maxLux > 0 ? (maxLux / 5).ceilToDouble() : 10,
190243
),
191244
),
192-
sideTitles: SideTitles(
193-
reservedSize: reservedSizeLeft,
194-
showTitles: true,
195-
getTitlesWidget: (value, meta) {
196-
return SideTitleWidget(
197-
meta: meta,
198-
child: Text(
199-
value.toInt().toString(),
200-
style: TextStyle(
201-
color: chartTextColor,
202-
fontSize: chartFontSize,
203-
),
204-
),
205-
);
206-
},
207-
interval: maxLux > 0 ? (maxLux / 5).ceilToDouble() : 10,
245+
rightTitles: AxisTitles(
246+
sideTitles: SideTitles(
247+
showTitles: false, reservedSize: reservedSizeRight),
208248
),
209249
),
210-
rightTitles: const AxisTitles(
211-
sideTitles: SideTitles(showTitles: false),
250+
gridData: FlGridData(
251+
show: true,
252+
drawHorizontalLine: true,
253+
drawVerticalLine: true,
254+
horizontalInterval: maxLux > 0 ? (maxLux / 5).ceilToDouble() : 10,
255+
verticalInterval: timeInterval,
212256
),
213-
),
214-
gridData: FlGridData(
215-
show: true,
216-
drawHorizontalLine: true,
217-
drawVerticalLine: true,
218-
horizontalInterval: maxLux > 0 ? (maxLux / 5).ceilToDouble() : 10,
219-
verticalInterval: timeInterval,
220-
),
221-
borderData: FlBorderData(
222-
show: true,
223-
border: Border(
224-
bottom: BorderSide(color: chartBorderColor),
225-
left: BorderSide(color: chartBorderColor),
226-
top: BorderSide(color: chartBorderColor),
227-
right: BorderSide(color: chartBorderColor),
257+
borderData: FlBorderData(
258+
show: true,
259+
border: Border(
260+
bottom: BorderSide(color: chartBorderColor),
261+
left: BorderSide(color: chartBorderColor),
262+
top: BorderSide(color: chartBorderColor),
263+
right: BorderSide(color: chartBorderColor),
264+
),
228265
),
266+
minY: 0,
267+
maxY: maxLux > 0 ? (maxLux * 1.1) : 100,
268+
maxX: maxTime > 0 ? maxTime : 10,
269+
minX: minTime,
270+
clipData: const FlClipData.all(),
271+
lineBarsData: [
272+
LineChartBarData(
273+
spots: spots,
274+
isCurved: true,
275+
color: chartLineColor,
276+
barWidth: screenWidth < 400 ? 1.5 : 2.0,
277+
isStrokeCapRound: true,
278+
dotData: const FlDotData(show: false),
279+
belowBarData: BarAreaData(show: false),
280+
),
281+
],
229282
),
230-
minY: 0,
231-
maxY: maxLux > 0 ? (maxLux * 1.1) : 100,
232-
maxX: maxTime > 0 ? maxTime : 10,
233-
minX: minTime,
234-
clipData: const FlClipData.all(),
235-
lineBarsData: [
236-
LineChartBarData(
237-
spots: spots,
238-
isCurved: true,
239-
color: chartLineColor,
240-
barWidth: screenWidth < 400 ? 1.5 : 2.0,
241-
isStrokeCapRound: true,
242-
dotData: const FlDotData(show: false),
243-
belowBarData: BarAreaData(show: false),
244-
),
245-
],
246283
),
247284
);
248285
}

0 commit comments

Comments
 (0)