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 'tables.dart'; part 'database.g.dart'; @DriftDatabase(tables: [ Rides, PerformanceRuns, TelemetrySamples, RideEvents, GarageMotorcycles, FieldTestSessions, FieldTestEvents, FieldTestGpsRecords, FieldTestImuRecords, ]) class AppDatabase extends _$AppDatabase { AppDatabase() : super(_openConnection()); AppDatabase.forTesting(super.e); @override int get schemaVersion => 4; @override MigrationStrategy get migration { return MigrationStrategy( onCreate: (Migrator m) async { await m.createAll(); }, onUpgrade: (Migrator m, int from, int to) async { if (from < 2) { // Add new columns to Rides 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); // Create new tables 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); } }, ); } // Insert a new ride and return its ID Future startRide() async { return into(rides).insert(RidesCompanion.insert( startTime: DateTime.now(), )); } // Complete a ride Future endRide(int rideId, RidesCompanion data) async { await (update(rides)..where((t) => t.id.equals(rideId))).write(data.copyWith( endTime: Value(DateTime.now()), )); } // Get all rides Future> getAllRides() => select(rides).get(); // Add a performance run Future addPerformanceRun(PerformanceRunsCompanion run) { return into(performanceRuns).insert(run); } // Get best 0-60 time Future getBest0to60() async { final query = select(performanceRuns) ..where((t) => t.type.equals('0-60')) ..orderBy([(t) => OrderingTerm(expression: t.timeMs, mode: OrderingMode.asc)]) ..limit(1); final result = await query.getSingleOrNull(); return result?.timeMs; } } LazyDatabase _openConnection() { return LazyDatabase(() async { final dbFolder = await getApplicationDocumentsDirectory(); final file = File(p.join(dbFolder.path, 'db.sqlite')); return NativeDatabase(file); }); } final databaseProvider = Provider((ref) { final db = AppDatabase(); ref.onDispose(db.close); return db; });