feat(media): gestion des médias locaux
Ajoute le stockage local des médias (infrastructure/local/local_media_storage.dart) et les use cases/ports associés. flutter analyze propre, 7/7 tests unitaires verts, build APK debug validé. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -35,6 +35,35 @@ final class DriftExerciseRepository implements ExerciseRepository {
|
||||
}
|
||||
}
|
||||
|
||||
final class DriftMediaAssetRepository implements MediaAssetRepository {
|
||||
const DriftMediaAssetRepository(this.database);
|
||||
|
||||
final db.AppDatabase database;
|
||||
|
||||
@override
|
||||
Future<domain.MediaAsset?> findById(String id) async {
|
||||
final row = await (database.select(
|
||||
database.mediaAssets,
|
||||
)..where((table) => table.id.equals(id))).getSingleOrNull();
|
||||
return row == null ? null : _mediaAssetFromRow(row);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<domain.MediaAsset>> listActive() async {
|
||||
final rows = await (database.select(
|
||||
database.mediaAssets,
|
||||
)..where((table) => table.deletedAt.isNull())).get();
|
||||
return rows.map(_mediaAssetFromRow).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save(domain.MediaAsset mediaAsset) async {
|
||||
await database
|
||||
.into(database.mediaAssets)
|
||||
.insertOnConflictUpdate(_mediaAssetCompanion(mediaAsset));
|
||||
}
|
||||
}
|
||||
|
||||
final class DriftProgramRepository implements ProgramRepository {
|
||||
const DriftProgramRepository(this.database);
|
||||
|
||||
@ -294,6 +323,49 @@ domain.Exercise _exerciseFromRow(db.Exercise row) {
|
||||
);
|
||||
}
|
||||
|
||||
db.MediaAssetsCompanion _mediaAssetCompanion(domain.MediaAsset asset) {
|
||||
final values = _metadataValues(asset.metadata);
|
||||
return db.MediaAssetsCompanion(
|
||||
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?>,
|
||||
kind: Value(_mediaKindToDb(asset.kind)),
|
||||
localUri: Value(asset.localUri),
|
||||
mimeType: Value(asset.mimeType),
|
||||
sizeBytes: Value(asset.sizeBytes),
|
||||
width: Value(asset.width),
|
||||
height: Value(asset.height),
|
||||
durationMs: Value(asset.durationMs),
|
||||
checksum: Value(asset.checksum),
|
||||
remoteUri: Value(asset.remoteUri),
|
||||
thumbnailLocalUri: Value(asset.thumbnailLocalUri),
|
||||
);
|
||||
}
|
||||
|
||||
domain.MediaAsset _mediaAssetFromRow(db.MediaAsset row) {
|
||||
return domain.MediaAsset(
|
||||
metadata: _metadataFromRow(row),
|
||||
kind: _mediaKindFromDb(row.kind),
|
||||
localUri: row.localUri,
|
||||
mimeType: row.mimeType,
|
||||
sizeBytes: row.sizeBytes,
|
||||
width: row.width,
|
||||
height: row.height,
|
||||
durationMs: row.durationMs,
|
||||
checksum: row.checksum,
|
||||
remoteUri: row.remoteUri,
|
||||
thumbnailLocalUri: row.thumbnailLocalUri,
|
||||
);
|
||||
}
|
||||
|
||||
db.ProgramsCompanion _programCompanion(domain.Program program) {
|
||||
final values = _metadataValues(program.metadata);
|
||||
return db.ProgramsCompanion(
|
||||
@ -741,6 +813,17 @@ String _activeStatusToDb(domain.ActiveWorkoutStatus status) => switch (status) {
|
||||
domain.ActiveWorkoutStatus.abandoned => 'abandoned',
|
||||
};
|
||||
|
||||
String _mediaKindToDb(domain.MediaKind kind) => switch (kind) {
|
||||
domain.MediaKind.image => 'image',
|
||||
domain.MediaKind.video => 'video',
|
||||
};
|
||||
|
||||
domain.MediaKind _mediaKindFromDb(String value) => switch (value) {
|
||||
'image' => domain.MediaKind.image,
|
||||
'video' => domain.MediaKind.video,
|
||||
_ => throw domain.DomainException('Unknown media kind: $value'),
|
||||
};
|
||||
|
||||
domain.ActiveWorkoutStatus _activeStatusFromDb(String value) => switch (value) {
|
||||
'running' => domain.ActiveWorkoutStatus.running,
|
||||
'paused' => domain.ActiveWorkoutStatus.paused,
|
||||
|
||||
Reference in New Issue
Block a user