import '../domain/domain.dart'; abstract interface class Clock { DateTime now(); } final class SystemClock implements Clock { const SystemClock(); @override DateTime now() => DateTime.now().toUtc(); } abstract interface class IdGenerator { String newId(); } enum RemoteAuthFailure { invalidCredentials, emailAlreadyUsed, network, unknown, } final class RemoteAuthException implements Exception { const RemoteAuthException(this.failure, [this.message]); final RemoteAuthFailure failure; final String? message; @override String toString() => message ?? failure.name; } final class RemoteAuthResult { const RemoteAuthResult({ required this.userId, required this.email, required this.token, required this.expiresAt, }); final String userId; final String email; final String token; final DateTime expiresAt; } abstract interface class AuthTokenStore { Future saveToken(String token, DateTime expiresAt); Future readToken(); Future clearToken(); } abstract interface class OnlineAccountRepository { Future currentSession(); Future saveSession(UserAccountSession session); Future clearSession(); } abstract interface class RemoteAuthApi { Future register({ required String email, required String password, String? displayName, }); Future login({ required String email, required String password, }); Future logout(String token); } abstract interface class ExerciseRepository { Future findById(String id); Future> listActive(); Future isReferencedByProgram(String id); Future save(Exercise exercise); } final class StoredMediaFile { const StoredMediaFile({ required this.localUri, required this.mimeType, required this.sizeBytes, this.width, this.height, this.durationMs, }); final String localUri; final String? mimeType; final int sizeBytes; final int? width; final int? height; final int? durationMs; } abstract interface class LocalMediaStorage { Future importFile({ required String sourcePath, required MediaKind kind, required String stableFileName, }); Future> listManagedLocalUris(); Future deleteByLocalUri(String localUri); } abstract interface class MediaAssetRepository { Future findById(String id); Future> listActive(); Future save(MediaAsset mediaAsset); } abstract interface class ProgramRepository { Future findById(String id); Future> listActive(); Future save(Program program); Future saveExercise(ProgramExercise exercise); Future replaceExercises(Program program, DateTime deletedAt); } abstract interface class WorkoutTemplateRepository { Future findById(String id); Future> listActive(); Future save(WorkoutTemplate template); Future saveProgram(WorkoutTemplateProgram program); Future saveOverride(WorkoutTemplateExerciseOverride override); Future replaceComposition(WorkoutTemplate template, DateTime deletedAt); } abstract interface class ActiveSessionRepository { Future findById(String id); Future findOpen(); Future save(ActiveWorkoutSession session); Future saveSetResult(ActiveSetResult result); Future saveRestState(ActiveRestState restState); Future saveScoreStopwatchState(ActiveScoreStopwatchState state); Future saveExerciseStepProgressState( ActiveExerciseStepProgressState state, ); Future saveExerciseStepResult(ActiveExerciseStepResult result); Future deleteScoreStopwatchState({ required String sessionId, required int programIndex, required int exerciseIndex, required int setIndex, required DateTime deletedAt, }); Future findRestStateById(String id); Future findScoreStopwatchState({ required String sessionId, required int programIndex, required int exerciseIndex, required int setIndex, }); Future findExerciseStepProgressState({ required String sessionId, required int programIndex, required int exerciseIndex, required int setIndex, }); Future> listSetResults(String sessionId); Future> listExerciseStepProgressStates( String sessionId, ); Future> listExerciseStepResults( String sessionId, ); Future> listRestStates(String sessionId); Future> listScoreStopwatchStates( String sessionId, ); } abstract interface class WorkoutHistoryRepository { Future findById(String id); Future> listActive(); Future save(WorkoutHistory history); Future saveSetResult(WorkoutHistorySetResult result); Future saveStepResult(WorkoutHistoryStepResult result); Future delete(String id, DateTime deletedAt); } final class SyncRunSummary { const SyncRunSummary({ required this.pushedChanges, required this.pulledChanges, }); final int pushedChanges; final int pulledChanges; } abstract interface class SyncGateway { Future synchronize(); } final class NoOpSyncGateway implements SyncGateway { const NoOpSyncGateway(); @override Future synchronize() async { return const SyncRunSummary(pushedChanges: 0, pulledChanges: 0); } }