import 'dart:io'; import 'package:drift/drift.dart'; import 'package:drift/native.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as p; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:uuid/uuid.dart'; import 'tables.dart'; part 'database.g.dart'; @DriftDatabase(tables: [Rides, PerformanceRuns, TelemetrySamples, RideEvents, GarageMotorcycles, FieldTestSessions, FieldTestEvents, FieldTestSummaries, FieldTestGpsRecords, FieldTestImuRecords]) class AppDatabase extends _$AppDatabase { AppDatabase() : super(_openConnection()); AppDatabase.forTesting(super.e); static const _uuid = Uuid(); @override int get schemaVersion => 6; @override MigrationStrategy get migration => MigrationStrategy( onCreate: (Migrator m) async => m.createAll(), onUpgrade: (Migrator m, int from, int to) async { if (from < 2) { await m.addColumn(rides, rides.distance); await m.addColumn(rides, rides.movingTime); await m.addColumn(rides, rides.stoppedTime); await m.addColumn(rides, rides.averageSpeed); await m.addColumn(rides, rides.topSpeed); await m.addColumn(rides, rides.elevationGain); await m.addColumn(rides, rides.elevationLoss); await m.createTable(telemetrySamples); await m.createTable(rideEvents); } if (from < 3) { await m.createTable(garageMotorcycles); await m.addColumn(rides, rides.motorcycleId); await m.addColumn(rides, rides.motorcycleYear); await m.addColumn(rides, rides.motorcycleMake); await m.addColumn(rides, rides.motorcycleModel); await m.addColumn(rides, rides.motorcycleVariant); } if (from < 4) { await m.createTable(fieldTestSessions); await m.createTable(fieldTestEvents); await m.createTable(fieldTestGpsRecords); await m.createTable(fieldTestImuRecords); } if (from < 5) { await m.createTable(fieldTestSummaries); try { await m.addColumn(fieldTestEvents, fieldTestEvents.rideId); await m.addColumn(fieldTestEvents, fieldTestEvents.telemetryTimestamp); await m.addColumn(fieldTestEvents, fieldTestEvents.gpsAgeMs); await m.addColumn(fieldTestEvents, fieldTestEvents.speed); await m.addColumn(fieldTestEvents, fieldTestEvents.latitude); await m.addColumn(fieldTestEvents, fieldTestEvents.longitude); await m.addColumn(fieldTestEvents, fieldTestEvents.gpsAccuracy); await m.addColumn(fieldTestEvents, fieldTestEvents.leanAngle); await m.addColumn(fieldTestEvents, fieldTestEvents.longitudinalG); await m.addColumn(fieldTestEvents, fieldTestEvents.lateralG); await m.addColumn(fieldTestEvents, fieldTestEvents.overallConfidence); await m.addColumn(fieldTestEvents, fieldTestEvents.metadata); } catch (_) {} } if (from < 6) { await m.addColumn(rides, rides.cloudRideId); final existingRides = await select(rides).get(); for (final ride in existingRides) { final cloudId = 'ride_${_uuid.v4()}'; await (update(rides)..where((r) => r.id.equals(ride.id))).write( RidesCompanion(cloudRideId: Value(cloudId)), ); } } }, ); Future startRide() async { return into(rides).insert(RidesCompanion.insert( cloudRideId: Value('ride_${_uuid.v4()}'), startTime: DateTime.now(), )); } Future endRide(int rideId, RidesCompanion data) async { await (update(rides)..where((t) => t.id.equals(rideId))).write(data.copyWith(endTime: Value(DateTime.now()))); } } LazyDatabase _openConnection() { return LazyDatabase(() async { final dbFolder = await getApplicationDocumentsDirectory(); final file = File(p.join(dbFolder.path, 'motorsignal.sqlite')); return NativeDatabase.createInBackground(file); }); } final databaseProvider = Provider((ref) { final db = AppDatabase(); ref.onDispose(db.close); return db; });