Commit 43c83d3
Changed files (4)
app
lib
features
statistics
test
features
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(