Commit 0df5140e03bbb3adc83e42410be70ed96168890a

Authored by 权海
1 parent 1429e580

feat(ui):实时压力推送剔除is_workout

... ... @@ -410,10 +410,7 @@ class HealthRawDataCoreService {
: result.realtimeStressPoints.reduce(
(a, b) => a.rawEndTime >= b.rawEndTime ? a : b,
);
final shouldSkipRealtimeStressNotification =
latestRealtimeStressPoint?.isWorkout ?? false;
final realtimeWindow = latestRealtimeStressPoint == null ||
shouldSkipRealtimeStressNotification
final realtimeWindow = latestRealtimeStressPoint == null
? const <HealthRawRealtimeStressPoint>[]
: await _localStore.queryRealtimeStressPoints(
userId: result.userId,
... ...
... ... @@ -108,10 +108,16 @@ class HealthRawLocalNotificationBuilder {
List<HealthRawRealtimeStressPoint> realtimeWindow,
HealthRawLocalNotificationRecord? record,
) {
final valid = realtimeWindow
.where((e) => e.result >= 1 && e.result <= 100)
.toList()
final window = [...realtimeWindow]
..sort((a, b) => a.rawEndTime.compareTo(b.rawEndTime));
final lastWorkoutIndex = window.lastIndexWhere(
(point) => point.isWorkout || point.isWorkoutRecovery,
);
final stressWindow = lastWorkoutIndex < 0
? window
: window.skip(lastWorkoutIndex + 1).toList();
final valid =
stressWindow.where((e) => e.result >= 1 && e.result <= 100).toList();
if (valid.length < _realtimeMinPointCount) return null;
final latest = valid.last;
... ...
... ... @@ -80,7 +80,6 @@ void main() {
);
api.calls.clear();
store.realtimeNotificationWindowQueryCount = 0;
final second = await service.startCoreCaculate(
endTime: base + 800,
readChunkDays: 1,
... ... @@ -91,7 +90,6 @@ void main() {
second.realtimeStressPoints.map((e) => e.rawEndTime),
[base + 720],
);
expect(store.realtimeNotificationWindowQueryCount, 0);
expect(
api.firstCallStart(HealthDataUploadType.hrv.type),
lessThanOrEqualTo(base + 120),
... ... @@ -871,7 +869,6 @@ class _MemoryHealthRawStressLocalStore extends HealthRawStressLocalStore {
final Map<int, List<HealthRawDailyStressPoint>> _daily = {};
final Map<int, List<HealthRawSleepResult>> _sleep = {};
final List<String> operationLog;
var realtimeNotificationWindowQueryCount = 0;
void insertDailyStress(HealthRawDailyStressPoint point) {
final byDate = <int, HealthRawDailyStressPoint>{
... ... @@ -1042,9 +1039,6 @@ class _MemoryHealthRawStressLocalStore extends HealthRawStressLocalStore {
required int endTime,
}) async {
operationLog.add('queryRealtimeStressPoints');
if (endTime - startTime <= Duration.secondsPerHour) {
realtimeNotificationWindowQueryCount += 1;
}
return (_realtime[userId] ?? <HealthRawRealtimeStressPoint>[])
.where((e) => e.rawEndTime >= startTime && e.rawEndTime <= endTime)
.toList();
... ...
... ... @@ -123,6 +123,50 @@ void main() {
expect(notifications, isEmpty);
});
test('resets realtime stress window after workout point', () {
final base = _seconds(DateTime(2026, 1, 1, 9));
final notifications = builder.build(
result: HealthRawStressCalculationResult(
userId: 1,
hrvStressPoints: const [],
realtimeStressPoints: [_realtimePoint(base + 12 * 300, 70)],
dailyStressPoints: const [],
),
hasExistingHrv: false,
realtimeWindow: [
for (var i = 0; i < 3; i++) _realtimePoint(base + i * 300, 70),
_realtimePoint(base + 3 * 300, 70, isWorkout: true),
for (var i = 4; i < 13; i++) _realtimePoint(base + i * 300, 70),
],
record: const HealthRawLocalNotificationRecord(),
);
expect(notifications, isEmpty);
});
test('builds realtime stress notification after workout reset window refills',
() {
final base = _seconds(DateTime(2026, 1, 1, 9));
final notifications = builder.build(
result: HealthRawStressCalculationResult(
userId: 1,
hrvStressPoints: const [],
realtimeStressPoints: [_realtimePoint(base + 13 * 300, 70)],
dailyStressPoints: const [],
),
hasExistingHrv: false,
realtimeWindow: [
for (var i = 0; i < 3; i++) _realtimePoint(base + i * 300, 30),
_realtimePoint(base + 3 * 300, 30, isWorkoutRecovery: true),
for (var i = 4; i < 14; i++) _realtimePoint(base + i * 300, 70),
],
record: const HealthRawLocalNotificationRecord(),
);
expect(notifications, hasLength(1));
expect(notifications.single.title, '注意压力 · 09:05-10:05');
});
}
int _seconds(DateTime time) => time.millisecondsSinceEpoch ~/ 1000;
... ... @@ -147,6 +191,8 @@ HealthRawRealtimeStressPoint _realtimePoint(
int rawEndTime,
double result, {
bool isSleepLikely = false,
bool isWorkout = false,
bool isWorkoutRecovery = false,
}) {
return HealthRawRealtimeStressPoint(
userId: 1,
... ... @@ -157,8 +203,8 @@ HealthRawRealtimeStressPoint _realtimePoint(
sourceEndTime: rawEndTime,
flags: HealthRawPointFlags(
isSleepLikely: isSleepLikely,
isWorkout: false,
isWorkoutRecovery: false,
isWorkout: isWorkout,
isWorkoutRecovery: isWorkoutRecovery,
isSuspectedActivity: false,
),
);
... ...