/// Composition root. /// /// The one place that decides which concrete implementations the app runs with. Tests /// override these rather than reaching for singletons — the mistake the native app made /// with `AppDatabase.getDatabase()` and `TripRepository.get()`, which is how an /// instrumented test once wiped a real device's rides. library; import 'package:drift/drift.dart' show driftRuntimeOptions; import 'package:drift_flutter/drift_flutter.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../data/database.dart'; import '../data/trip_repository.dart'; import '../domain/models.dart'; import '../recording/geolocator_location_source.dart'; import '../recording/location_source.dart'; import '../recording/recording_engine.dart'; /// The Drift database, opened against app-private storage. /// /// Overridden in tests with an in-memory instance. final databaseProvider = Provider((ref) { driftRuntimeOptions.dontWarnAboutMultipleDatabases = true; final db = AppDatabase(driftDatabase(name: 'rippr_db')); ref.onDispose(db.close); return db; }); final tripRepositoryProvider = Provider( (ref) => TripRepository(ref.watch(databaseProvider)), ); /// Overridden in tests with [FakeLocationSource]. final locationSourceProvider = Provider((ref) { final source = GeolocatorLocationSource(); ref.onDispose(source.dispose); return source; }); final recordingEngineProvider = Provider((ref) { final engine = RecordingEngine( repository: ref.watch(tripRepositoryProvider), locationSource: ref.watch(locationSourceProvider), ); ref.onDispose(engine.dispose); return engine; }); // --- Reactive state --------------------------------------------------------- /// The in-progress ride, straight from the database. /// /// Recording state is derived, never held as a flag — that is what makes it survive /// process death. final activeTripProvider = StreamProvider( (ref) => ref.watch(tripRepositoryProvider).watchActiveTrip(), ); final completedTripsProvider = StreamProvider>( (ref) => ref.watch(tripRepositoryProvider).watchCompletedTrips(), ); final recorderStateProvider = StreamProvider((ref) { final engine = ref.watch(recordingEngineProvider); return engine.stateStream; });