feat(server): implemente synchronisation et serveur avec fixtures (#187)

- Implémente la couche de synchronisation avec le serveur
- Ajoute les fixtures versionnées pour les tests
- Met à jour Drift database et repositories pour le support sync
- Améliore les tests de synchronisation
- Corrige et améliore le watch companion pour la collecte de métriques

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-04 23:07:31 +02:00
parent d1edb2397e
commit fe3608cc4a
31 changed files with 5056 additions and 394 deletions

View File

@ -5,6 +5,7 @@ import 'package:gametime/application/application.dart';
import 'package:gametime/domain/domain.dart';
import 'package:gametime/infrastructure/infrastructure.dart'
hide
ActiveWorkoutTelemetryWindowState,
WorkoutHistory,
WorkoutHistorySetResult,
WorkoutHistoryStepResult,
@ -311,6 +312,25 @@ void main() {
),
);
await Future<void>.delayed(Duration.zero);
expect(telemetryRepository.samples, isEmpty);
native.emitSensorSample(
WatchSensorSample(
sampleId: 'sample-2',
sessionId: 'session-1',
recordedAtEpochMs: _now
.add(const Duration(seconds: 20))
.millisecondsSinceEpoch,
programIndex: 0,
exerciseIndex: 0,
setIndex: 0,
stepIndex: 0,
heartRateBpm: 130,
distanceMeters: 520,
caloriesKcal: 45,
),
);
await Future<void>.delayed(Duration.zero);
expect(
telemetryRepository.samples.single.id,
@ -658,6 +678,7 @@ final class _FakeWorkoutTelemetryRepository
implements WorkoutTelemetryRepository {
final samples = <WorkoutTelemetrySample>[];
final aggregates = <WorkoutTelemetryAggregate>[];
final windowStates = <String, ActiveWorkoutTelemetryWindowState>{};
@override
Future<bool> saveSample(WorkoutTelemetrySample sample) async {
@ -668,6 +689,23 @@ final class _FakeWorkoutTelemetryRepository
return true;
}
@override
Future<ActiveWorkoutTelemetryWindowState?> findWindowState(
String sessionId,
) async {
return windowStates[sessionId];
}
@override
Future<void> saveWindowState(ActiveWorkoutTelemetryWindowState state) async {
windowStates[state.sessionId] = state;
}
@override
Future<void> deleteWindowState(String sessionId) async {
windowStates.remove(sessionId);
}
@override
Future<List<WorkoutTelemetrySample>> listSamples(String sessionId) async {
return samples