feat(application): couche application avec use cases et repositories
Ajoute les entités du domaine (domain/entities.dart), les ports de repository (application/ports.dart), les use cases (application/use_cases.dart) et leur implémentation Drift (infrastructure/local/drift_repositories.dart). flutter analyze propre, tests unitaires verts, build APK debug validé. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
751
lib/infrastructure/local/drift_repositories.dart
Normal file
751
lib/infrastructure/local/drift_repositories.dart
Normal file
@ -0,0 +1,751 @@
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
import '../../application/application.dart';
|
||||
import '../../domain/domain.dart' as domain;
|
||||
import 'app_database.dart' as db;
|
||||
|
||||
final class DriftExerciseRepository implements ExerciseRepository {
|
||||
const DriftExerciseRepository(this.database);
|
||||
|
||||
final db.AppDatabase database;
|
||||
|
||||
@override
|
||||
Future<domain.Exercise?> findById(String id) async {
|
||||
final row = await (database.select(
|
||||
database.exercises,
|
||||
)..where((table) => table.id.equals(id))).getSingleOrNull();
|
||||
return row == null ? null : _exerciseFromRow(row);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<domain.Exercise>> listActive() async {
|
||||
final rows =
|
||||
await (database.select(database.exercises)
|
||||
..where((table) => table.deletedAt.isNull())
|
||||
..orderBy([(table) => OrderingTerm.asc(table.name)]))
|
||||
.get();
|
||||
return rows.map(_exerciseFromRow).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save(domain.Exercise exercise) async {
|
||||
await database
|
||||
.into(database.exercises)
|
||||
.insertOnConflictUpdate(_exerciseCompanion(exercise));
|
||||
}
|
||||
}
|
||||
|
||||
final class DriftProgramRepository implements ProgramRepository {
|
||||
const DriftProgramRepository(this.database);
|
||||
|
||||
final db.AppDatabase database;
|
||||
|
||||
@override
|
||||
Future<domain.Program?> findById(String id) async {
|
||||
final row = await (database.select(
|
||||
database.programs,
|
||||
)..where((table) => table.id.equals(id))).getSingleOrNull();
|
||||
if (row == null) {
|
||||
return null;
|
||||
}
|
||||
final exercises =
|
||||
await (database.select(database.programExercises)
|
||||
..where((table) => table.programId.equals(id))
|
||||
..orderBy([(table) => OrderingTerm.asc(table.position)]))
|
||||
.get();
|
||||
return _programFromRow(
|
||||
row,
|
||||
exercises.map(_programExerciseFromRow).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save(domain.Program program) async {
|
||||
await database
|
||||
.into(database.programs)
|
||||
.insertOnConflictUpdate(_programCompanion(program));
|
||||
for (final exercise in program.exercises) {
|
||||
await saveExercise(exercise);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveExercise(domain.ProgramExercise exercise) async {
|
||||
await database
|
||||
.into(database.programExercises)
|
||||
.insertOnConflictUpdate(_programExerciseCompanion(exercise));
|
||||
}
|
||||
}
|
||||
|
||||
final class DriftWorkoutTemplateRepository
|
||||
implements WorkoutTemplateRepository {
|
||||
const DriftWorkoutTemplateRepository(this.database);
|
||||
|
||||
final db.AppDatabase database;
|
||||
|
||||
@override
|
||||
Future<domain.WorkoutTemplate?> findById(String id) async {
|
||||
final row = await (database.select(
|
||||
database.workoutTemplates,
|
||||
)..where((table) => table.id.equals(id))).getSingleOrNull();
|
||||
if (row == null) {
|
||||
return null;
|
||||
}
|
||||
final programs =
|
||||
await (database.select(database.workoutTemplatePrograms)
|
||||
..where((table) => table.workoutTemplateId.equals(id))
|
||||
..orderBy([(table) => OrderingTerm.asc(table.position)]))
|
||||
.get();
|
||||
final programIds = programs.map((program) => program.id).toSet();
|
||||
final overrides = await (database.select(
|
||||
database.workoutTemplateExerciseOverrides,
|
||||
)..where((table) => table.workoutTemplateProgramId.isIn(programIds))).get();
|
||||
return _workoutTemplateFromRow(
|
||||
row,
|
||||
programs.map(_workoutTemplateProgramFromRow).toList(),
|
||||
overrides.map(_workoutTemplateExerciseOverrideFromRow).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save(domain.WorkoutTemplate template) async {
|
||||
await database
|
||||
.into(database.workoutTemplates)
|
||||
.insertOnConflictUpdate(_workoutTemplateCompanion(template));
|
||||
for (final program in template.programs) {
|
||||
await saveProgram(program);
|
||||
}
|
||||
for (final override in template.overrides) {
|
||||
await saveOverride(override);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveProgram(domain.WorkoutTemplateProgram program) async {
|
||||
await database
|
||||
.into(database.workoutTemplatePrograms)
|
||||
.insertOnConflictUpdate(_workoutTemplateProgramCompanion(program));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveOverride(
|
||||
domain.WorkoutTemplateExerciseOverride override,
|
||||
) async {
|
||||
await database
|
||||
.into(database.workoutTemplateExerciseOverrides)
|
||||
.insertOnConflictUpdate(
|
||||
_workoutTemplateExerciseOverrideCompanion(override),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final class DriftActiveSessionRepository implements ActiveSessionRepository {
|
||||
const DriftActiveSessionRepository(this.database);
|
||||
|
||||
final db.AppDatabase database;
|
||||
|
||||
@override
|
||||
Future<domain.ActiveWorkoutSession?> findById(String id) async {
|
||||
final row = await (database.select(
|
||||
database.activeWorkoutSessions,
|
||||
)..where((table) => table.id.equals(id))).getSingleOrNull();
|
||||
return row == null ? null : _activeWorkoutSessionFromRow(row);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save(domain.ActiveWorkoutSession session) async {
|
||||
await database
|
||||
.into(database.activeWorkoutSessions)
|
||||
.insertOnConflictUpdate(_activeWorkoutSessionCompanion(session));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveSetResult(domain.ActiveSetResult result) async {
|
||||
await database
|
||||
.into(database.activeSetResults)
|
||||
.insertOnConflictUpdate(_activeSetResultCompanion(result));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveRestState(domain.ActiveRestState restState) async {
|
||||
await database
|
||||
.into(database.activeRestStates)
|
||||
.insertOnConflictUpdate(_activeRestStateCompanion(restState));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<domain.ActiveSetResult>> listSetResults(String sessionId) async {
|
||||
final rows =
|
||||
await (database.select(database.activeSetResults)
|
||||
..where((table) => table.activeWorkoutSessionId.equals(sessionId))
|
||||
..orderBy([
|
||||
(table) => OrderingTerm.asc(table.programIndex),
|
||||
(table) => OrderingTerm.asc(table.exerciseIndex),
|
||||
(table) => OrderingTerm.asc(table.setIndex),
|
||||
]))
|
||||
.get();
|
||||
return rows.map(_activeSetResultFromRow).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<domain.ActiveRestState>> listRestStates(String sessionId) async {
|
||||
final rows =
|
||||
await (database.select(database.activeRestStates)
|
||||
..where((table) => table.activeWorkoutSessionId.equals(sessionId))
|
||||
..orderBy([(table) => OrderingTerm.asc(table.startedAt)]))
|
||||
.get();
|
||||
return rows.map(_activeRestStateFromRow).toList();
|
||||
}
|
||||
}
|
||||
|
||||
final class DriftWorkoutHistoryRepository implements WorkoutHistoryRepository {
|
||||
const DriftWorkoutHistoryRepository(this.database);
|
||||
|
||||
final db.AppDatabase database;
|
||||
|
||||
@override
|
||||
Future<void> save(domain.WorkoutHistory history) async {
|
||||
await database
|
||||
.into(database.workoutHistories)
|
||||
.insertOnConflictUpdate(_workoutHistoryCompanion(history));
|
||||
for (final result in history.results) {
|
||||
await saveSetResult(result);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveSetResult(domain.WorkoutHistorySetResult result) async {
|
||||
await database
|
||||
.into(database.workoutHistorySetResults)
|
||||
.insertOnConflictUpdate(_workoutHistorySetResultCompanion(result));
|
||||
}
|
||||
}
|
||||
|
||||
domain.EntityMetadata _metadataFromRow(dynamic row) {
|
||||
return domain.EntityMetadata(
|
||||
id: row.id as String,
|
||||
createdAt: row.createdAt as DateTime,
|
||||
updatedAt: row.updatedAt as DateTime,
|
||||
deletedAt: row.deletedAt as DateTime?,
|
||||
schemaVersion: row.schemaVersion as int,
|
||||
syncState: _syncStateFromDb(row.syncState as String),
|
||||
localRevision: row.localRevision as int,
|
||||
originDeviceId: row.originDeviceId as String,
|
||||
futureOwnerProfileId: row.futureOwnerProfileId as String?,
|
||||
lastSyncedAt: row.lastSyncedAt as DateTime?,
|
||||
remoteRevision: row.remoteRevision as String?,
|
||||
);
|
||||
}
|
||||
|
||||
List<Value<Object?>> _metadataValues(domain.EntityMetadata metadata) => [
|
||||
Value(metadata.id),
|
||||
Value(metadata.createdAt),
|
||||
Value(metadata.updatedAt),
|
||||
Value(metadata.deletedAt),
|
||||
Value(metadata.schemaVersion),
|
||||
Value(_syncStateToDb(metadata.syncState)),
|
||||
Value(metadata.localRevision),
|
||||
Value(metadata.originDeviceId),
|
||||
Value(metadata.futureOwnerProfileId),
|
||||
Value(metadata.lastSyncedAt),
|
||||
Value(metadata.remoteRevision),
|
||||
];
|
||||
|
||||
db.ExercisesCompanion _exerciseCompanion(domain.Exercise exercise) {
|
||||
final values = _metadataValues(exercise.metadata);
|
||||
return db.ExercisesCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
name: Value(exercise.name),
|
||||
description: Value(exercise.description),
|
||||
imageMediaId: Value(exercise.imageMediaId),
|
||||
videoMediaId: Value(exercise.videoMediaId),
|
||||
hasTimeMeasure: Value(exercise.hasTimeMeasure),
|
||||
hasRepsMeasure: Value(exercise.hasRepsMeasure),
|
||||
hasScoreMeasure: Value(exercise.hasScoreMeasure),
|
||||
scoreLabel: Value(exercise.scoreLabel),
|
||||
scoreUnit: Value(exercise.scoreUnit),
|
||||
archivedAt: Value(exercise.archivedAt),
|
||||
);
|
||||
}
|
||||
|
||||
domain.Exercise _exerciseFromRow(db.Exercise row) {
|
||||
return domain.Exercise(
|
||||
metadata: _metadataFromRow(row),
|
||||
name: row.name,
|
||||
description: row.description,
|
||||
imageMediaId: row.imageMediaId,
|
||||
videoMediaId: row.videoMediaId,
|
||||
hasTimeMeasure: row.hasTimeMeasure,
|
||||
hasRepsMeasure: row.hasRepsMeasure,
|
||||
hasScoreMeasure: row.hasScoreMeasure,
|
||||
scoreLabel: row.scoreLabel,
|
||||
scoreUnit: row.scoreUnit,
|
||||
archivedAt: row.archivedAt,
|
||||
);
|
||||
}
|
||||
|
||||
db.ProgramsCompanion _programCompanion(domain.Program program) {
|
||||
final values = _metadataValues(program.metadata);
|
||||
return db.ProgramsCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
name: Value(program.name),
|
||||
defaultRestSeconds: Value(program.defaultRestSeconds),
|
||||
);
|
||||
}
|
||||
|
||||
domain.Program _programFromRow(
|
||||
db.Program row,
|
||||
List<domain.ProgramExercise> exercises,
|
||||
) {
|
||||
return domain.Program(
|
||||
metadata: _metadataFromRow(row),
|
||||
name: row.name,
|
||||
defaultRestSeconds: row.defaultRestSeconds,
|
||||
exercises: exercises,
|
||||
);
|
||||
}
|
||||
|
||||
db.ProgramExercisesCompanion _programExerciseCompanion(
|
||||
domain.ProgramExercise exercise,
|
||||
) {
|
||||
final values = _metadataValues(exercise.metadata);
|
||||
return db.ProgramExercisesCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
programId: Value(exercise.programId),
|
||||
sourceExerciseId: Value(exercise.sourceExerciseId),
|
||||
position: Value(exercise.position),
|
||||
exerciseNameSnapshot: Value(exercise.exerciseNameSnapshot),
|
||||
exerciseDescriptionSnapshot: Value(exercise.exerciseDescriptionSnapshot),
|
||||
exerciseImageMediaIdSnapshot: Value(exercise.exerciseImageMediaIdSnapshot),
|
||||
exerciseVideoMediaIdSnapshot: Value(exercise.exerciseVideoMediaIdSnapshot),
|
||||
exerciseArchivedSnapshot: Value(exercise.exerciseArchivedSnapshot),
|
||||
availableTimeSnapshot: Value(exercise.availableTimeSnapshot),
|
||||
availableRepsSnapshot: Value(exercise.availableRepsSnapshot),
|
||||
availableScoreSnapshot: Value(exercise.availableScoreSnapshot),
|
||||
scoreLabelSnapshot: Value(exercise.scoreLabelSnapshot),
|
||||
scoreUnitSnapshot: Value(exercise.scoreUnitSnapshot),
|
||||
setsCount: Value(exercise.setsCount),
|
||||
timeEnabled: Value(exercise.timeEnabled),
|
||||
repsEnabled: Value(exercise.repsEnabled),
|
||||
scoreEnabled: Value(exercise.scoreEnabled),
|
||||
targetTimeSeconds: Value(exercise.targetTimeSeconds),
|
||||
targetReps: Value(exercise.targetReps),
|
||||
targetScore: Value(exercise.targetScore),
|
||||
restSecondsOverride: Value(exercise.restSecondsOverride),
|
||||
);
|
||||
}
|
||||
|
||||
domain.ProgramExercise _programExerciseFromRow(db.ProgramExercise row) {
|
||||
return domain.ProgramExercise(
|
||||
metadata: _metadataFromRow(row),
|
||||
programId: row.programId,
|
||||
sourceExerciseId: row.sourceExerciseId,
|
||||
position: row.position,
|
||||
exerciseNameSnapshot: row.exerciseNameSnapshot,
|
||||
exerciseDescriptionSnapshot: row.exerciseDescriptionSnapshot,
|
||||
exerciseImageMediaIdSnapshot: row.exerciseImageMediaIdSnapshot,
|
||||
exerciseVideoMediaIdSnapshot: row.exerciseVideoMediaIdSnapshot,
|
||||
exerciseArchivedSnapshot: row.exerciseArchivedSnapshot,
|
||||
availableTimeSnapshot: row.availableTimeSnapshot,
|
||||
availableRepsSnapshot: row.availableRepsSnapshot,
|
||||
availableScoreSnapshot: row.availableScoreSnapshot,
|
||||
scoreLabelSnapshot: row.scoreLabelSnapshot,
|
||||
scoreUnitSnapshot: row.scoreUnitSnapshot,
|
||||
setsCount: row.setsCount,
|
||||
timeEnabled: row.timeEnabled,
|
||||
repsEnabled: row.repsEnabled,
|
||||
scoreEnabled: row.scoreEnabled,
|
||||
targetTimeSeconds: row.targetTimeSeconds,
|
||||
targetReps: row.targetReps,
|
||||
targetScore: row.targetScore,
|
||||
restSecondsOverride: row.restSecondsOverride,
|
||||
);
|
||||
}
|
||||
|
||||
db.WorkoutTemplatesCompanion _workoutTemplateCompanion(
|
||||
domain.WorkoutTemplate template,
|
||||
) {
|
||||
final values = _metadataValues(template.metadata);
|
||||
return db.WorkoutTemplatesCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
name: Value(template.name),
|
||||
lastStartedAt: Value(template.lastStartedAt),
|
||||
);
|
||||
}
|
||||
|
||||
domain.WorkoutTemplate _workoutTemplateFromRow(
|
||||
db.WorkoutTemplate row,
|
||||
List<domain.WorkoutTemplateProgram> programs,
|
||||
List<domain.WorkoutTemplateExerciseOverride> overrides,
|
||||
) {
|
||||
return domain.WorkoutTemplate(
|
||||
metadata: _metadataFromRow(row),
|
||||
name: row.name,
|
||||
lastStartedAt: row.lastStartedAt,
|
||||
programs: programs,
|
||||
overrides: overrides,
|
||||
);
|
||||
}
|
||||
|
||||
db.WorkoutTemplateProgramsCompanion _workoutTemplateProgramCompanion(
|
||||
domain.WorkoutTemplateProgram program,
|
||||
) {
|
||||
final values = _metadataValues(program.metadata);
|
||||
return db.WorkoutTemplateProgramsCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
workoutTemplateId: Value(program.workoutTemplateId),
|
||||
sourceProgramId: Value(program.sourceProgramId),
|
||||
position: Value(program.position),
|
||||
programNameSnapshot: Value(program.programNameSnapshot),
|
||||
defaultRestSecondsSnapshot: Value(program.defaultRestSecondsSnapshot),
|
||||
programSnapshotJson: Value(program.programSnapshotJson),
|
||||
);
|
||||
}
|
||||
|
||||
domain.WorkoutTemplateProgram _workoutTemplateProgramFromRow(
|
||||
db.WorkoutTemplateProgram row,
|
||||
) {
|
||||
return domain.WorkoutTemplateProgram(
|
||||
metadata: _metadataFromRow(row),
|
||||
workoutTemplateId: row.workoutTemplateId,
|
||||
sourceProgramId: row.sourceProgramId,
|
||||
position: row.position,
|
||||
programNameSnapshot: row.programNameSnapshot,
|
||||
defaultRestSecondsSnapshot: row.defaultRestSecondsSnapshot,
|
||||
programSnapshotJson: row.programSnapshotJson,
|
||||
);
|
||||
}
|
||||
|
||||
db.WorkoutTemplateExerciseOverridesCompanion
|
||||
_workoutTemplateExerciseOverrideCompanion(
|
||||
domain.WorkoutTemplateExerciseOverride override,
|
||||
) {
|
||||
final values = _metadataValues(override.metadata);
|
||||
return db.WorkoutTemplateExerciseOverridesCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
workoutTemplateProgramId: Value(override.workoutTemplateProgramId),
|
||||
snapshotProgramExerciseId: Value(override.snapshotProgramExerciseId),
|
||||
setsCountOverride: Value(override.setsCountOverride),
|
||||
targetTimeSecondsOverride: Value(override.targetTimeSecondsOverride),
|
||||
targetRepsOverride: Value(override.targetRepsOverride),
|
||||
targetScoreOverride: Value(override.targetScoreOverride),
|
||||
);
|
||||
}
|
||||
|
||||
domain.WorkoutTemplateExerciseOverride _workoutTemplateExerciseOverrideFromRow(
|
||||
db.WorkoutTemplateExerciseOverride row,
|
||||
) {
|
||||
return domain.WorkoutTemplateExerciseOverride(
|
||||
metadata: _metadataFromRow(row),
|
||||
workoutTemplateProgramId: row.workoutTemplateProgramId,
|
||||
snapshotProgramExerciseId: row.snapshotProgramExerciseId,
|
||||
setsCountOverride: row.setsCountOverride,
|
||||
targetTimeSecondsOverride: row.targetTimeSecondsOverride,
|
||||
targetRepsOverride: row.targetRepsOverride,
|
||||
targetScoreOverride: row.targetScoreOverride,
|
||||
);
|
||||
}
|
||||
|
||||
db.ActiveWorkoutSessionsCompanion _activeWorkoutSessionCompanion(
|
||||
domain.ActiveWorkoutSession session,
|
||||
) {
|
||||
final values = _metadataValues(session.metadata);
|
||||
return db.ActiveWorkoutSessionsCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
sourceWorkoutTemplateId: Value(session.sourceWorkoutTemplateId),
|
||||
status: Value(_activeStatusToDb(session.status)),
|
||||
startedAt: Value(session.startedAt),
|
||||
pausedAt: Value(session.pausedAt),
|
||||
endedAt: Value(session.endedAt),
|
||||
lastPersistedAt: Value(session.lastPersistedAt),
|
||||
elapsedActiveMs: Value(session.elapsedActiveMs),
|
||||
currentProgramIndex: Value(session.currentProgramIndex),
|
||||
currentExerciseIndex: Value(session.currentExerciseIndex),
|
||||
currentSetIndex: Value(session.currentSetIndex),
|
||||
resolvedTemplateSnapshotJson: Value(session.resolvedTemplateSnapshotJson),
|
||||
);
|
||||
}
|
||||
|
||||
domain.ActiveWorkoutSession _activeWorkoutSessionFromRow(
|
||||
db.ActiveWorkoutSession row,
|
||||
) {
|
||||
return domain.ActiveWorkoutSession(
|
||||
metadata: _metadataFromRow(row),
|
||||
sourceWorkoutTemplateId: row.sourceWorkoutTemplateId,
|
||||
status: _activeStatusFromDb(row.status),
|
||||
startedAt: row.startedAt,
|
||||
pausedAt: row.pausedAt,
|
||||
endedAt: row.endedAt,
|
||||
lastPersistedAt: row.lastPersistedAt,
|
||||
elapsedActiveMs: row.elapsedActiveMs,
|
||||
currentProgramIndex: row.currentProgramIndex,
|
||||
currentExerciseIndex: row.currentExerciseIndex,
|
||||
currentSetIndex: row.currentSetIndex,
|
||||
resolvedTemplateSnapshotJson: row.resolvedTemplateSnapshotJson,
|
||||
);
|
||||
}
|
||||
|
||||
db.ActiveSetResultsCompanion _activeSetResultCompanion(
|
||||
domain.ActiveSetResult result,
|
||||
) {
|
||||
final values = _metadataValues(result.metadata);
|
||||
return db.ActiveSetResultsCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
activeWorkoutSessionId: Value(result.activeWorkoutSessionId),
|
||||
programSnapshotId: Value(result.programSnapshotId),
|
||||
exerciseSnapshotId: Value(result.exerciseSnapshotId),
|
||||
programIndex: Value(result.programIndex),
|
||||
exerciseIndex: Value(result.exerciseIndex),
|
||||
setIndex: Value(result.setIndex),
|
||||
startedAt: Value(result.startedAt),
|
||||
completedAt: Value(result.completedAt),
|
||||
actualTimeMs: Value(result.actualTimeMs),
|
||||
actualReps: Value(result.actualReps),
|
||||
actualScore: Value(result.actualScore),
|
||||
scoreLabelSnapshot: Value(result.scoreLabelSnapshot),
|
||||
scoreUnitSnapshot: Value(result.scoreUnitSnapshot),
|
||||
note: Value(result.note),
|
||||
);
|
||||
}
|
||||
|
||||
domain.ActiveSetResult _activeSetResultFromRow(db.ActiveSetResult row) {
|
||||
return domain.ActiveSetResult(
|
||||
metadata: _metadataFromRow(row),
|
||||
activeWorkoutSessionId: row.activeWorkoutSessionId,
|
||||
programSnapshotId: row.programSnapshotId,
|
||||
exerciseSnapshotId: row.exerciseSnapshotId,
|
||||
programIndex: row.programIndex,
|
||||
exerciseIndex: row.exerciseIndex,
|
||||
setIndex: row.setIndex,
|
||||
startedAt: row.startedAt,
|
||||
completedAt: row.completedAt,
|
||||
actualTimeMs: row.actualTimeMs,
|
||||
actualReps: row.actualReps,
|
||||
actualScore: row.actualScore,
|
||||
scoreLabelSnapshot: row.scoreLabelSnapshot,
|
||||
scoreUnitSnapshot: row.scoreUnitSnapshot,
|
||||
note: row.note,
|
||||
);
|
||||
}
|
||||
|
||||
db.ActiveRestStatesCompanion _activeRestStateCompanion(
|
||||
domain.ActiveRestState restState,
|
||||
) {
|
||||
final values = _metadataValues(restState.metadata);
|
||||
return db.ActiveRestStatesCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
activeWorkoutSessionId: Value(restState.activeWorkoutSessionId),
|
||||
afterProgramIndex: Value(restState.afterProgramIndex),
|
||||
afterExerciseIndex: Value(restState.afterExerciseIndex),
|
||||
afterSetIndex: Value(restState.afterSetIndex),
|
||||
plannedRestSeconds: Value(restState.plannedRestSeconds),
|
||||
adjustedRestSeconds: Value(restState.adjustedRestSeconds),
|
||||
startedAt: Value(restState.startedAt),
|
||||
endedAt: Value(restState.endedAt),
|
||||
skippedAt: Value(restState.skippedAt),
|
||||
);
|
||||
}
|
||||
|
||||
domain.ActiveRestState _activeRestStateFromRow(db.ActiveRestState row) {
|
||||
return domain.ActiveRestState(
|
||||
metadata: _metadataFromRow(row),
|
||||
activeWorkoutSessionId: row.activeWorkoutSessionId,
|
||||
afterProgramIndex: row.afterProgramIndex,
|
||||
afterExerciseIndex: row.afterExerciseIndex,
|
||||
afterSetIndex: row.afterSetIndex,
|
||||
plannedRestSeconds: row.plannedRestSeconds,
|
||||
adjustedRestSeconds: row.adjustedRestSeconds,
|
||||
startedAt: row.startedAt,
|
||||
endedAt: row.endedAt,
|
||||
skippedAt: row.skippedAt,
|
||||
);
|
||||
}
|
||||
|
||||
db.WorkoutHistoriesCompanion _workoutHistoryCompanion(
|
||||
domain.WorkoutHistory history,
|
||||
) {
|
||||
final values = _metadataValues(history.metadata);
|
||||
return db.WorkoutHistoriesCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
sourceWorkoutTemplateId: Value(history.sourceWorkoutTemplateId),
|
||||
sourceActiveWorkoutSessionId: Value(history.sourceActiveWorkoutSessionId),
|
||||
nameSnapshot: Value(history.nameSnapshot),
|
||||
startedAt: Value(history.startedAt),
|
||||
endedAt: Value(history.endedAt),
|
||||
totalActiveMs: Value(history.totalActiveMs),
|
||||
completed: Value(history.completed),
|
||||
historySnapshotJson: Value(history.historySnapshotJson),
|
||||
);
|
||||
}
|
||||
|
||||
db.WorkoutHistorySetResultsCompanion _workoutHistorySetResultCompanion(
|
||||
domain.WorkoutHistorySetResult result,
|
||||
) {
|
||||
final values = _metadataValues(result.metadata);
|
||||
return db.WorkoutHistorySetResultsCompanion(
|
||||
id: values[0] as Value<String>,
|
||||
createdAt: values[1] as Value<DateTime>,
|
||||
updatedAt: values[2] as Value<DateTime>,
|
||||
deletedAt: values[3] as Value<DateTime?>,
|
||||
schemaVersion: values[4] as Value<int>,
|
||||
syncState: values[5] as Value<String>,
|
||||
localRevision: values[6] as Value<int>,
|
||||
originDeviceId: values[7] as Value<String>,
|
||||
futureOwnerProfileId: values[8] as Value<String?>,
|
||||
lastSyncedAt: values[9] as Value<DateTime?>,
|
||||
remoteRevision: values[10] as Value<String?>,
|
||||
workoutHistoryId: Value(result.workoutHistoryId),
|
||||
programSnapshotId: Value(result.programSnapshotId),
|
||||
exerciseSnapshotId: Value(result.exerciseSnapshotId),
|
||||
programIndex: Value(result.programIndex),
|
||||
exerciseIndex: Value(result.exerciseIndex),
|
||||
setIndex: Value(result.setIndex),
|
||||
programNameSnapshot: Value(result.programNameSnapshot),
|
||||
exerciseNameSnapshot: Value(result.exerciseNameSnapshot),
|
||||
timeEnabledSnapshot: Value(result.timeEnabledSnapshot),
|
||||
repsEnabledSnapshot: Value(result.repsEnabledSnapshot),
|
||||
scoreEnabledSnapshot: Value(result.scoreEnabledSnapshot),
|
||||
targetTimeSecondsSnapshot: Value(result.targetTimeSecondsSnapshot),
|
||||
targetRepsSnapshot: Value(result.targetRepsSnapshot),
|
||||
targetScoreSnapshot: Value(result.targetScoreSnapshot),
|
||||
actualTimeMs: Value(result.actualTimeMs),
|
||||
actualReps: Value(result.actualReps),
|
||||
actualScore: Value(result.actualScore),
|
||||
scoreLabelSnapshot: Value(result.scoreLabelSnapshot),
|
||||
scoreUnitSnapshot: Value(result.scoreUnitSnapshot),
|
||||
startedAt: Value(result.startedAt),
|
||||
completedAt: Value(result.completedAt),
|
||||
);
|
||||
}
|
||||
|
||||
String _syncStateToDb(domain.SyncState state) => switch (state) {
|
||||
domain.SyncState.localOnly => 'localOnly',
|
||||
domain.SyncState.dirty => 'dirty',
|
||||
domain.SyncState.synced => 'synced',
|
||||
domain.SyncState.deleted => 'deleted',
|
||||
};
|
||||
|
||||
domain.SyncState _syncStateFromDb(String value) => switch (value) {
|
||||
'localOnly' => domain.SyncState.localOnly,
|
||||
'dirty' => domain.SyncState.dirty,
|
||||
'synced' => domain.SyncState.synced,
|
||||
'deleted' => domain.SyncState.deleted,
|
||||
_ => throw domain.DomainException('Unknown sync state: $value'),
|
||||
};
|
||||
|
||||
String _activeStatusToDb(domain.ActiveWorkoutStatus status) => switch (status) {
|
||||
domain.ActiveWorkoutStatus.running => 'running',
|
||||
domain.ActiveWorkoutStatus.paused => 'paused',
|
||||
domain.ActiveWorkoutStatus.savedExit => 'savedExit',
|
||||
domain.ActiveWorkoutStatus.completed => 'completed',
|
||||
domain.ActiveWorkoutStatus.abandoned => 'abandoned',
|
||||
};
|
||||
|
||||
domain.ActiveWorkoutStatus _activeStatusFromDb(String value) => switch (value) {
|
||||
'running' => domain.ActiveWorkoutStatus.running,
|
||||
'paused' => domain.ActiveWorkoutStatus.paused,
|
||||
'savedExit' => domain.ActiveWorkoutStatus.savedExit,
|
||||
'completed' => domain.ActiveWorkoutStatus.completed,
|
||||
'abandoned' => domain.ActiveWorkoutStatus.abandoned,
|
||||
_ => throw domain.DomainException('Unknown active workout status: $value'),
|
||||
};
|
||||
@ -1,2 +1,3 @@
|
||||
export 'app_database.dart';
|
||||
export 'drift_repositories.dart';
|
||||
export 'local_id.dart';
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
import 'dart:math';
|
||||
|
||||
import '../../application/ports.dart';
|
||||
|
||||
const _crockfordBase32 = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
|
||||
|
||||
final class LocalIdGenerator {
|
||||
final class LocalIdGenerator implements IdGenerator {
|
||||
LocalIdGenerator({Random? random}) : _random = random ?? Random.secure();
|
||||
|
||||
final Random _random;
|
||||
|
||||
@override
|
||||
String newId() => newUlid();
|
||||
|
||||
String newUlid({DateTime? now}) {
|
||||
final timestamp = (now ?? DateTime.now().toUtc()).millisecondsSinceEpoch;
|
||||
final buffer = StringBuffer();
|
||||
|
||||
Reference in New Issue
Block a user