fix(persistence): correctifs post-QA sur les repositories (ticket #13)

Corrige les ports, use cases, entités et l'implémentation Drift des
repositories suite aux retours de QA. flutter analyze propre, 24/24
tests verts, build APK debug validé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-17 22:14:07 +02:00
parent 009615c6a5
commit 9f9d0dbe3b
7 changed files with 227 additions and 0 deletions

View File

@ -80,6 +80,7 @@ abstract interface class ActiveSessionRepository {
Future<void> save(ActiveWorkoutSession session);
Future<void> saveSetResult(ActiveSetResult result);
Future<void> saveRestState(ActiveRestState restState);
Future<ActiveRestState?> findRestStateById(String id);
Future<List<ActiveSetResult>> listSetResults(String sessionId);
Future<List<ActiveRestState>> listRestStates(String sessionId);
}

View File

@ -803,6 +803,50 @@ final class ActiveWorkoutSessionUseCases {
return rest;
}
Future<ActiveRestState> adjustRestSeconds({
required String restStateId,
required int deltaSeconds,
}) async {
final rest = await sessionRepository.findRestStateById(restStateId);
if (rest == null) {
throw const DomainException('Active rest state not found.');
}
final now = clock.now();
final adjusted = rest.copyWith(
metadata: rest.metadata.touch(now),
adjustedRestSeconds: (rest.adjustedRestSeconds + deltaSeconds).clamp(
0,
1 << 31,
),
);
await sessionRepository.saveRestState(adjusted);
return adjusted;
}
Future<ActiveRestState> skipRest({required String restStateId}) async {
final rest = await sessionRepository.findRestStateById(restStateId);
if (rest == null) {
throw const DomainException('Active rest state not found.');
}
final now = clock.now();
final skipped = rest.copyWith(
metadata: rest.metadata.touch(now),
skippedAt: now,
);
await sessionRepository.saveRestState(skipped);
return skipped;
}
Future<ActiveRestState?> findActiveRest({required String sessionId}) async {
final restStates = await sessionRepository.listRestStates(sessionId);
final active =
restStates
.where((rest) => rest.endedAt == null && rest.skippedAt == null)
.toList()
..sort((left, right) => right.startedAt.compareTo(left.startedAt));
return active.isEmpty ? null : active.first;
}
Future<ActiveWorkoutSession> _requiredSession(String sessionId) async {
final session = await sessionRepository.findById(sessionId);
if (session == null) {

View File

@ -631,6 +631,28 @@ final class ActiveRestState {
final DateTime startedAt;
final DateTime? endedAt;
final DateTime? skippedAt;
ActiveRestState copyWith({
EntityMetadata? metadata,
int? adjustedRestSeconds,
Object? endedAt = _unchanged,
Object? skippedAt = _unchanged,
}) {
return ActiveRestState(
metadata: metadata ?? this.metadata,
activeWorkoutSessionId: activeWorkoutSessionId,
afterProgramIndex: afterProgramIndex,
afterExerciseIndex: afterExerciseIndex,
afterSetIndex: afterSetIndex,
plannedRestSeconds: plannedRestSeconds,
adjustedRestSeconds: adjustedRestSeconds ?? this.adjustedRestSeconds,
startedAt: startedAt,
endedAt: endedAt == _unchanged ? this.endedAt : endedAt as DateTime?,
skippedAt: skippedAt == _unchanged
? this.skippedAt
: skippedAt as DateTime?,
);
}
}
final class WorkoutHistory {

View File

@ -398,6 +398,14 @@ final class DriftActiveSessionRepository implements ActiveSessionRepository {
.insertOnConflictUpdate(_activeRestStateCompanion(restState));
}
@override
Future<domain.ActiveRestState?> findRestStateById(String id) async {
final row = await (database.select(
database.activeRestStates,
)..where((table) => table.id.equals(id))).getSingleOrNull();
return row == null ? null : _activeRestStateFromRow(row);
}
@override
Future<List<domain.ActiveSetResult>> listSetResults(String sessionId) async {
final rows =