Commit 43c83d3

derdilla <82763757+derdilla@users.noreply.github.com>
2024-11-05 10:03:11
Correctly fill warn area at start of graph (#468)
* fix graph not filled at start * fix lints * test changes
1 parent 175c487
Changed files (4)
app/lib/features/statistics/value_graph.dart
@@ -11,7 +11,6 @@ import 'package:health_data_store/health_data_store.dart';
 import 'package:intl/intl.dart';
 import 'package:provider/provider.dart';
 
-
 /// A graph of [BloodPressureRecord] values.
 ///
 /// Note that this can't follow the users preferred unit as this would not allow
@@ -201,13 +200,18 @@ class _ValueGraphPainter extends CustomPainter {
     if (data.isEmpty) return;
 
     Path? path;
+    Path? warnPath = warnValue == null ? null : Path();
     for (final e in data) {
       final point = ui.Offset(_transformX(size, e.$1, range), _transformY(size, e.$2, minY, maxY));
       if (path != null) {
         path.lineTo(point.dx, point.dy);
+        warnPath?.lineTo(point.dx, point.dy);
       } else {
         path = Path();
         path.moveTo(point.dx, point.dy);
+
+        warnPath?.moveTo(_kLeftLegendWidth, _transformY(size, warnValue!, minY, maxY));
+        warnPath?.lineTo(point.dx, point.dy);
       }
     }
 
@@ -215,18 +219,17 @@ class _ValueGraphPainter extends CustomPainter {
     path = subPath(path, progress);
 
     if (warnValue != null) {
-      final graphPath = Path();
-      // FIXME: technically wont fill area before graph start
-      // (to see have the first value be above warn value and disable maskFilter)
-      graphPath.addPath(path, ui.Offset.zero);
-      graphPath.relativeLineTo(0, size.height);
+      assert(warnPath != null);
+
+      warnPath = subPath(warnPath!, progress);
+      warnPath.relativeLineTo(0, size.height);
 
       final y = _transformY(size, warnValue, minY, maxY);
 
       final warnRect = Rect.fromLTRB(_kLeftLegendWidth, 0, size.width, y);
       final clippedPath = Path.combine(
         PathOperation.intersect,
-        graphPath,
+        warnPath,
         Path()..addRect(warnRect),
       );
       canvas.drawPath(clippedPath, ui.Paint()
@@ -442,18 +445,15 @@ class _ValueGraphPainter extends CustomPainter {
 /// Create graph data from a list of blood pressure records.
 extension GraphData on List<BloodPressureRecord> {
   /// Get the timestamps and mmHg values of all non-null sys values.
-  Iterable<(DateTime, double)> sysGraph() => this
-    .map((r) => (r.time, r.sys?.mmHg.toDouble()))
+  Iterable<(DateTime, double)> sysGraph() => map((r) => (r.time, r.sys?.mmHg.toDouble()))
     .whereNot(((DateTime, double?) e) => e.$2 == null)
     .cast<(DateTime, double)>();
   /// Get the timestamps and mmHg values of all non-null dia values.
-  Iterable<(DateTime, double)> diaGraph() => this
-    .map((r) => (r.time, r.dia?.mmHg.toDouble()))
+  Iterable<(DateTime, double)> diaGraph() => map((r) => (r.time, r.dia?.mmHg.toDouble()))
     .whereNot(((DateTime, double?) e) => e.$2 == null)
     .cast<(DateTime, double)>();
   /// Get the timestamps and values as doubles of all non-null pul values.
-  Iterable<(DateTime, double)> pulGraph() => this
-    .map((r) => (r.time, r.pul?.toDouble()))
+  Iterable<(DateTime, double)> pulGraph() => map((r) => (r.time, r.pul?.toDouble()))
     .whereNot(((DateTime, double?) e) => e.$2 == null)
     .cast<(DateTime, double)>();
 }
app/test/features/statistics/value-graph-end-warn.png
Binary file
app/test/features/statistics/value-graph-start-warn.png
Binary file
app/test/features/statistics/value_graph_test.dart
@@ -127,6 +127,39 @@ void main() {
     final localizations = await AppLocalizations.delegate.load(const Locale('en'));
     expect(find.text(localizations.errNotEnoughDataToGraph), findsNothing);
   });
+
+  testWidgets('graph renders area at start correctly', (tester) async {
+    await tester.pumpWidget(_buildGraph([
+        mockRecord(time: DateTime(2003), sys: 170, dia: 100, pul: 50),
+        mockRecord(time: DateTime(2005), sys: 110, dia: 70, pul: 50),
+      ], [], [],
+      settings: Settings(
+        diaWarn: 75,
+        sysWarn: 120,
+      ),
+    ));
+    await tester.pumpAndSettle();
+    final localizations = await AppLocalizations.delegate.load(const Locale('en'));
+    expect(find.text(localizations.errNotEnoughDataToGraph), findsNothing);
+
+    await expectLater(find.byType(BloodPressureValueGraph), matchesGoldenFile('value-graph-start-warn.png'));
+  });
+  testWidgets('graph renders area at end correctly', (tester) async {
+    await tester.pumpWidget(_buildGraph([
+      mockRecord(time: DateTime(2005), sys: 170, dia: 100, pul: 50),
+      mockRecord(time: DateTime(2003), sys: 110, dia: 70, pul: 50),
+    ], [], [],
+      settings: Settings(
+        diaWarn: 75,
+        sysWarn: 120,
+      ),
+    ));
+    await tester.pumpAndSettle();
+    final localizations = await AppLocalizations.delegate.load(const Locale('en'));
+    expect(find.text(localizations.errNotEnoughDataToGraph), findsNothing);
+
+    await expectLater(find.byType(BloodPressureValueGraph), matchesGoldenFile('value-graph-end-warn.png'));
+  });
 }
 
 Widget _buildGraph(