Commit 09bd0687c72ef4ca5c47031ede09e838bc056c99

Authored by 权海
1 parent 116979b3

feat(ui):移除HRV计算后的时间间隔判断

... ... @@ -14,7 +14,6 @@ import '../../pigeon/health_kit_api.g.dart';
import '../../pigeon/health_kit_raw_data_api.g.dart';
import '../config/app_environment_config.dart';
import '../logging/app_logger.dart';
import '../util/app_toast.dart';
import 'health_raw_local_notification.dart';
import 'health_raw_stress_calculator.dart';
import 'health_sleep_calculator.dart';
... ... @@ -281,8 +280,6 @@ class HealthRawDataCoreService {
final latestSleepResultTime = await _localStore.latestSleepResultTime(
userId,
);
final isFirstCalculation =
hrvContextStart == null && realtimeContextStart == null;
final hrvStartTime = math.max(
hrvContextStart ?? requestedStartTime,
earliestStartTime,
... ... @@ -382,7 +379,7 @@ class HealthRawDataCoreService {
);
await _sendLocalNotificationsAfterCalculation(
result: storedResult,
previousHrvRawEndTime: latestHrvRawEndTime,
hasExistingHrv: latestHrvRawEndTime != null,
);
final calculateFinishedAt = DateTime.now();
_logInfo(
... ... @@ -393,7 +390,7 @@ class HealthRawDataCoreService {
Future<void> _sendLocalNotificationsAfterCalculation({
required HealthRawStressCalculationResult result,
required int? previousHrvRawEndTime,
required bool hasExistingHrv,
}) async {
if (result.hrvStressPoints.isEmpty &&
result.realtimeStressPoints.isEmpty &&
... ... @@ -420,7 +417,7 @@ class HealthRawDataCoreService {
);
final notifications = HealthRawLocalNotificationBuilder(l10n).build(
result: result,
previousHrvRawEndTime: previousHrvRawEndTime,
hasExistingHrv: hasExistingHrv,
realtimeWindow: realtimeWindow,
record: record,
);
... ...
... ... @@ -37,7 +37,6 @@ enum HealthRawLocalNotificationRecordType {
class HealthRawLocalNotificationBuilder {
const HealthRawLocalNotificationBuilder(this.l10n);
static const int _hrvMinIntervalSeconds = 2 * 60 * 60;
static const int _realtimeWindowSeconds = 60 * 60;
static const int _realtimeMinPointCount = 10;
... ... @@ -45,18 +44,14 @@ class HealthRawLocalNotificationBuilder {
List<HealthRawLocalNotification> build({
required HealthRawStressCalculationResult result,
required int? previousHrvRawEndTime,
required bool hasExistingHrv,
required List<HealthRawRealtimeStressPoint> realtimeWindow,
required HealthRawLocalNotificationRecord? record,
}) {
return [
if (_sleepNotification(result.sleepResults) case final notification?)
notification,
if (_hrvNotification(
result.hrvStressPoints,
previousHrvRawEndTime,
record,
)
if (_hrvNotification(result.hrvStressPoints, hasExistingHrv, record)
case final notification?)
notification,
if (_realtimeStressNotification(realtimeWindow, record)
... ... @@ -85,20 +80,14 @@ class HealthRawLocalNotificationBuilder {
HealthRawLocalNotification? _hrvNotification(
List<HealthRawHrvStressPoint> hrvPoints,
int? previousHrvRawEndTime,
bool hasExistingHrv,
HealthRawLocalNotificationRecord? record,
) {
if (!hasExistingHrv) return null;
if (hrvPoints.isEmpty) return null;
final sorted = [...hrvPoints]
..sort((a, b) => a.rawEndTime.compareTo(b.rawEndTime));
final latest = sorted.last;
final previousTime = sorted.length >= 2
? sorted[sorted.length - 2].rawEndTime
: previousHrvRawEndTime;
if (previousTime == null ||
latest.rawEndTime - previousTime < _hrvMinIntervalSeconds) {
return null;
}
if (record?.lastHrvTime == latest.rawEndTime) return null;
return HealthRawLocalNotification(
... ...
... ... @@ -26,7 +26,7 @@ void main() {
),
],
),
previousHrvRawEndTime: null,
hasExistingHrv: false,
realtimeWindow: const [],
record: const HealthRawLocalNotificationRecord(),
);
... ... @@ -37,7 +37,7 @@ void main() {
expect(notifications.single.link, healthRawTodayLink);
});
test('builds hrv notification when previous hrv is at least two hours away',
test('builds hrv notification when new hrv is calculated after first run',
() {
final latestTime = _seconds(DateTime(2026, 1, 1, 10));
final notifications = builder.build(
... ... @@ -49,7 +49,7 @@ void main() {
realtimeStressPoints: const [],
dailyStressPoints: const [],
),
previousHrvRawEndTime: latestTime - Duration.secondsPerHour * 2,
hasExistingHrv: true,
realtimeWindow: const [],
record: const HealthRawLocalNotificationRecord(),
);
... ... @@ -59,7 +59,7 @@ void main() {
expect(notifications.single.link, healthRawHrvChangeLink);
});
test('skips hrv notification when previous hrv is too close', () {
test('skips hrv notification on first calculation without existing hrv', () {
final latestTime = _seconds(DateTime(2026, 1, 1, 10));
final notifications = builder.build(
result: HealthRawStressCalculationResult(
... ... @@ -70,7 +70,7 @@ void main() {
realtimeStressPoints: const [],
dailyStressPoints: const [],
),
previousHrvRawEndTime: latestTime - Duration.secondsPerHour * 2 + 1,
hasExistingHrv: false,
realtimeWindow: const [],
record: const HealthRawLocalNotificationRecord(),
);
... ... @@ -87,7 +87,7 @@ void main() {
realtimeStressPoints: [_realtimePoint(base + 9 * 300, 70)],
dailyStressPoints: const [],
),
previousHrvRawEndTime: null,
hasExistingHrv: false,
realtimeWindow: [
for (var i = 0; i < 10; i++) _realtimePoint(base + i * 300, 70),
],
... ... @@ -111,7 +111,7 @@ void main() {
],
dailyStressPoints: const [],
),
previousHrvRawEndTime: null,
hasExistingHrv: false,
realtimeWindow: [
for (var i = 0; i < 9; i++) _realtimePoint(base + i * 300, 70),
_realtimePoint(base + 9 * 300, 70, isSleepLikely: true),
... ...