Ajoute la synchronisation client incrémentale LWW vers l'API serveur (application/use_cases.dart: SyncUseCases, ports.dart, migration Drift schemaVersion 10→11 pour les métadonnées de sync et mappings de ressources, infrastructure/remote/sync_api.dart) et l'écran de profil avec entrée sur l'accueil (presentation/profile_screen.dart, home_screen.dart, presentation.dart). Développés dans le même worktree partagé par DevBackend et DevFrontend ; commit combiné car test/presentation/home_screen_test.dart mélange authentiquement les deux tickets (le test de l'entrée Profil et la mise à jour du fake de bootstrap requise par le nouveau getter syncUseCases sur AppDependencies). Corrige au passage une couleur `crimson` inexistante dans le thème (remplacée par colorScheme.error) et une signature de paramètres positionnels/nommés incohérente sur un fake de test. flutter pub get OK, build_runner OK, dart format appliqué, analyze propre (mêmes infos préexistantes), 119/119 tests verts, build APK debug validé. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
159 lines
5.5 KiB
Dart
159 lines
5.5 KiB
Dart
import '../infrastructure/local/local.dart';
|
|
import '../infrastructure/remote/remote.dart';
|
|
import '../infrastructure/security/security.dart';
|
|
import 'application.dart';
|
|
|
|
abstract interface class AppDependencies {
|
|
AuthUseCases get authUseCases;
|
|
ExerciseUseCases get exerciseUseCases;
|
|
MediaUseCases get mediaUseCases;
|
|
ProgramUseCases get programUseCases;
|
|
WorkoutTemplateUseCases get workoutTemplateUseCases;
|
|
ActiveWorkoutSessionUseCases get activeWorkoutSessionUseCases;
|
|
ActiveExerciseStepUseCases get activeExerciseStepUseCases;
|
|
CloseWorkoutSessionUseCase get closeWorkoutSessionUseCase;
|
|
WorkoutHistoryUseCases get workoutHistoryUseCases;
|
|
SyncUseCases get syncUseCases;
|
|
}
|
|
|
|
final class AppBootstrap implements AppDependencies {
|
|
AppBootstrap._({
|
|
required this.database,
|
|
required this.authUseCases,
|
|
required this.exerciseUseCases,
|
|
required this.mediaUseCases,
|
|
required this.programUseCases,
|
|
required this.workoutTemplateUseCases,
|
|
required this.activeWorkoutSessionUseCases,
|
|
required this.activeExerciseStepUseCases,
|
|
required this.closeWorkoutSessionUseCase,
|
|
required this.workoutHistoryUseCases,
|
|
required this.syncUseCases,
|
|
required this.syncGateway,
|
|
});
|
|
|
|
final AppDatabase database;
|
|
@override
|
|
final AuthUseCases authUseCases;
|
|
@override
|
|
final ExerciseUseCases exerciseUseCases;
|
|
@override
|
|
final MediaUseCases mediaUseCases;
|
|
@override
|
|
final ProgramUseCases programUseCases;
|
|
@override
|
|
final WorkoutTemplateUseCases workoutTemplateUseCases;
|
|
@override
|
|
final ActiveWorkoutSessionUseCases activeWorkoutSessionUseCases;
|
|
@override
|
|
final ActiveExerciseStepUseCases activeExerciseStepUseCases;
|
|
@override
|
|
final CloseWorkoutSessionUseCase closeWorkoutSessionUseCase;
|
|
@override
|
|
final WorkoutHistoryUseCases workoutHistoryUseCases;
|
|
@override
|
|
final SyncUseCases syncUseCases;
|
|
final SyncGateway syncGateway;
|
|
|
|
static Future<AppBootstrap> create() async {
|
|
final database = AppDatabase.open();
|
|
await database.customSelect('SELECT 1').get();
|
|
final exerciseRepository = DriftExerciseRepository(database);
|
|
final mediaRepository = DriftMediaAssetRepository(database);
|
|
final onlineAccountRepository = DriftOnlineAccountRepository(database);
|
|
final syncMetadataRepository = DriftSyncMetadataRepository(database);
|
|
final mappingRepository = DriftRemoteResourceMappingRepository(database);
|
|
final localSyncChangeRepository = DriftLocalSyncChangeRepository(database);
|
|
final programRepository = DriftProgramRepository(database);
|
|
final templateRepository = DriftWorkoutTemplateRepository(database);
|
|
final activeSessionRepository = DriftActiveSessionRepository(database);
|
|
final historyRepository = DriftWorkoutHistoryRepository(database);
|
|
final ids = LocalIdGenerator();
|
|
const clock = SystemClock();
|
|
const originDeviceId = 'local-device';
|
|
final remoteAuthApi = HttpRemoteAuthApi(
|
|
HttpApiClient(baseUrl: Uri.parse(HttpApiClient.defaultBaseUrl)),
|
|
);
|
|
final remoteSyncApi = HttpRemoteSyncApi(
|
|
HttpApiClient(baseUrl: Uri.parse(HttpApiClient.defaultBaseUrl)),
|
|
);
|
|
|
|
return AppBootstrap._(
|
|
database: database,
|
|
authUseCases: AuthUseCases(
|
|
tokenStore: const SecureStorageAuthTokenStore(),
|
|
accountRepository: onlineAccountRepository,
|
|
remoteAuthApi: remoteAuthApi,
|
|
clock: clock,
|
|
ids: ids,
|
|
),
|
|
exerciseUseCases: ExerciseUseCases(
|
|
repository: exerciseRepository,
|
|
programRepository: programRepository,
|
|
clock: clock,
|
|
ids: ids,
|
|
originDeviceId: originDeviceId,
|
|
),
|
|
mediaUseCases: MediaUseCases(
|
|
mediaRepository: mediaRepository,
|
|
exerciseRepository: exerciseRepository,
|
|
storage: const PathProviderLocalMediaStorage(),
|
|
clock: clock,
|
|
ids: ids,
|
|
originDeviceId: originDeviceId,
|
|
),
|
|
programUseCases: ProgramUseCases(
|
|
programRepository: programRepository,
|
|
exerciseRepository: exerciseRepository,
|
|
templateRepository: templateRepository,
|
|
clock: clock,
|
|
ids: ids,
|
|
originDeviceId: originDeviceId,
|
|
),
|
|
workoutTemplateUseCases: WorkoutTemplateUseCases(
|
|
templateRepository: templateRepository,
|
|
programRepository: programRepository,
|
|
clock: clock,
|
|
ids: ids,
|
|
originDeviceId: originDeviceId,
|
|
),
|
|
activeWorkoutSessionUseCases: ActiveWorkoutSessionUseCases(
|
|
sessionRepository: activeSessionRepository,
|
|
templateRepository: templateRepository,
|
|
clock: clock,
|
|
ids: ids,
|
|
originDeviceId: originDeviceId,
|
|
),
|
|
activeExerciseStepUseCases: ActiveExerciseStepUseCases(
|
|
sessionRepository: activeSessionRepository,
|
|
clock: clock,
|
|
ids: ids,
|
|
originDeviceId: originDeviceId,
|
|
),
|
|
closeWorkoutSessionUseCase: CloseWorkoutSessionUseCase(
|
|
sessionRepository: activeSessionRepository,
|
|
historyRepository: historyRepository,
|
|
clock: clock,
|
|
ids: ids,
|
|
originDeviceId: originDeviceId,
|
|
),
|
|
workoutHistoryUseCases: WorkoutHistoryUseCases(
|
|
repository: historyRepository,
|
|
clock: clock,
|
|
),
|
|
syncUseCases: SyncUseCases(
|
|
tokenStore: const SecureStorageAuthTokenStore(),
|
|
remoteSyncApi: remoteSyncApi,
|
|
metadataRepository: syncMetadataRepository,
|
|
mappingRepository: mappingRepository,
|
|
localChanges: localSyncChangeRepository,
|
|
clock: clock,
|
|
deviceId: originDeviceId,
|
|
),
|
|
syncGateway: const NoOpSyncGateway(),
|
|
);
|
|
}
|
|
|
|
Future<void> dispose() => database.close();
|
|
}
|