Commit 0c4b23264fe3cfcb334be50295beb8941ba5d72d

Authored by 刘宏哲
1 parent a6833148

feat(app): activity burn report remove sleep range

... ... @@ -117,8 +117,6 @@ class ApiActivityBurnReportDataSource implements ActivityBurnReportDataSource {
time.isBefore(date.add(const Duration(days: 1))))
ActivityBurnHeartRatePoint(time: time, bpm: bpm.toDouble()),
]..sort((a, b) => a.time.compareTo(b.time));
final sleepRange = _dailySleepRange(date, data.sleepTimeList);
return ActivityBurnReport(
date: date,
activeEnergy:
... ... @@ -134,47 +132,11 @@ class ApiActivityBurnReportDataSource implements ActivityBurnReportDataSource {
heartRate: ActivityBurnHeartRateSummary(
startTime: date,
endTime: points.isEmpty ? null : points.last.time,
sleepStartTime: sleepRange?.start,
sleepEndTime: sleepRange?.end,
points: points,
),
);
}
_SleepRange? _dailySleepRange(
DateTime date,
List<SleepTimeList>? sleepTimeList,
) {
final dayStart = _normalizeDate(date);
final dayEnd = dayStart.add(const Duration(days: 1));
DateTime? earliestStart;
DateTime? latestEndInDay;
for (final item in sleepTimeList ?? const <SleepTimeList>[]) {
final from = _parseDateTime(item.fromTime, fallbackDate: dayStart);
final to = _parseDateTime(item.toTime, fallbackDate: dayStart);
if (from == null || to == null || !to.isAfter(from)) continue;
if (!from.isBefore(dayEnd) || !to.isAfter(dayStart)) continue;
final visibleStart = from.isBefore(dayStart) ? dayStart : from;
if (earliestStart == null || visibleStart.isBefore(earliestStart)) {
earliestStart = visibleStart;
}
final visibleEnd = to.isAfter(dayEnd) ? dayEnd : to;
if (!visibleEnd.isBefore(dayStart) && !visibleEnd.isAfter(dayEnd)) {
if (latestEndInDay == null || visibleEnd.isAfter(latestEndInDay)) {
latestEndInDay = visibleEnd;
}
}
}
final start = earliestStart;
final end = latestEndInDay;
if (start == null || end == null || !end.isAfter(start)) return null;
return _SleepRange(start, end);
}
Value? _dailyOverallValues(
DateTime date,
List<OverallList>? overallList,
... ... @@ -311,10 +273,3 @@ class ApiActivityBurnReportDataSource implements ActivityBurnReportDataSource {
int _dateKey(DateTime date) =>
date.year * 10000 + date.month * 100 + date.day;
}
class _SleepRange {
const _SleepRange(this.start, this.end);
final DateTime start;
final DateTime end;
}
... ...
... ... @@ -32,16 +32,12 @@ class ActivityBurnHeartRateSummary {
const ActivityBurnHeartRateSummary({
this.startTime,
this.endTime,
this.sleepStartTime,
this.sleepEndTime,
this.userAge,
this.points = const [],
});
final DateTime? startTime;
final DateTime? endTime;
final DateTime? sleepStartTime;
final DateTime? sleepEndTime;
final int? userAge;
final List<ActivityBurnHeartRatePoint> points;
... ...
... ... @@ -137,8 +137,6 @@ class _DailyReportContent extends StatelessWidget {
return ActivityBurnHeartRateSummary(
startTime: dailyReport.date,
endTime: dailyReport.date,
sleepStartTime: summary.sleepStartTime,
sleepEndTime: summary.sleepEndTime,
userAge: summary.userAge,
points: summary.points,
);
... ...
... ... @@ -6,7 +6,6 @@ import 'package:flutter/material.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'package:intl/intl.dart';
import '../../../../r.dart';
import '../../report_common/widgets/health_report_subject_scope.dart';
import '../models/activity_burn_report_models.dart';
import 'activity_burn_trend_lines.dart';
... ... @@ -21,7 +20,6 @@ class ActivityBurnHeartRateZoneCard extends StatelessWidget {
static const _h1 = Color(0xFF0F0F11);
static const _h3 = Color(0xFFB0B0B6);
static const _brand = Color(0xFF845EEE);
static const _active = Color(0xFFFF5279);
static const _warm = Color(0xFFFF9A6E);
static const _stand = Color(0xFF7B9BFB);
... ... @@ -41,8 +39,6 @@ class ActivityBurnHeartRateZoneCard extends StatelessWidget {
Widget build(BuildContext context) {
final start = _startTime;
final axis = _HeartRateAxis.fromSummary(summary, start);
final sleepRange = summary.hasData ? _sleepRange(start, axis.maxX) : null;
return Container(
height: 273,
padding: const EdgeInsets.fromLTRB(20, 20, 14, 16),
... ... @@ -69,7 +65,7 @@ class ActivityBurnHeartRateZoneCard extends StatelessWidget {
SizedBox(
height: _chartHeight,
child: LayoutBuilder(
builder: (context, constraints) {
builder: (_, __) {
return Stack(
fit: StackFit.expand,
alignment: Alignment.center,
... ... @@ -89,20 +85,6 @@ class ActivityBurnHeartRateZoneCard extends StatelessWidget {
top: 0,
child: LineChart(_chartData()),
),
if (sleepRange != null)
Positioned(
top: 0,
left: _sleepIconLeft(
sleepRange,
axis.maxX,
constraints.maxWidth,
),
child: Image.asset(
R.assetsImagesHealthBedIcon,
width: 12,
height: 12,
),
),
if (!summary.hasData)
Positioned(
left: 0,
... ... @@ -130,25 +112,10 @@ class ActivityBurnHeartRateZoneCard extends StatelessWidget {
);
}
double _sleepIconLeft(
_SleepRange range,
double maxX,
double chartWidth,
) {
const rightTitleWidth = 28.0;
const iconWidth = 12.0;
final plotWidth = math.max(0, chartWidth - rightTitleWidth);
final centerX = (range.startX + range.endX) / 2;
return (centerX / maxX * plotWidth - iconWidth / 2)
.clamp(0, math.max(0, chartWidth - iconWidth))
.toDouble();
}
LineChartData _chartData() {
final start = _startTime;
final axis = _HeartRateAxis.fromSummary(summary, start);
final points = _points(start, axis.endTime);
final sleepRange = _sleepRange(start, axis.maxX);
return LineChartData(
minX: 0,
... ... @@ -219,11 +186,7 @@ class ActivityBurnHeartRateZoneCard extends StatelessWidget {
),
lineBarsData: points.isEmpty
? [_emptyPlaceholderBar(axis)]
: [
if (sleepRange != null)
_sleepRangeBar(sleepRange, axis.maxY, axis.minY),
..._lineSegments(points, start),
],
: _lineSegments(points, start),
);
}
... ... @@ -240,47 +203,6 @@ class ActivityBurnHeartRateZoneCard extends StatelessWidget {
);
}
LineChartBarData _sleepRangeBar(
_SleepRange range,
double maxY,
double minY,
) {
return LineChartBarData(
spots: [FlSpot(range.startX, maxY), FlSpot(range.endX, maxY)],
color: _brand,
barWidth: 2,
isCurved: false,
dotData: const FlDotData(show: false),
belowBarData: BarAreaData(
show: true,
cutOffY: minY,
applyCutOffY: true,
gradient: const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0x4D845EEE), Color(0x00845EEE)],
),
),
);
}
_SleepRange? _sleepRange(DateTime start, double maxX) {
final sleepStart = summary.sleepStartTime;
final sleepEnd = summary.sleepEndTime;
if (sleepStart == null ||
sleepEnd == null ||
!sleepEnd.isAfter(sleepStart)) {
return null;
}
final startX = sleepStart.difference(start).inMinutes.toDouble();
final endX = sleepEnd.difference(start).inMinutes.toDouble();
final visibleStart = startX.clamp(0, maxX).toDouble();
final visibleEnd = endX.clamp(0, maxX).toDouble();
if (visibleEnd <= visibleStart) return null;
return _SleepRange(visibleStart, visibleEnd);
}
DateTime get _startTime {
if (summary.startTime != null) return _dayStart(summary.startTime!);
if (summary.points.isNotEmpty) return _dayStart(summary.points.first.time);
... ... @@ -531,10 +453,3 @@ class _HeartRateSegment {
final Color color;
final List<FlSpot> spots;
}
class _SleepRange {
const _SleepRange(this.startX, this.endX);
final double startX;
final double endX;
}
... ...