feat: working connection, conn setting, and gear ratio setting for universal shifters
This commit is contained in:
143
lib/database/database.dart
Normal file
143
lib/database/database.dart
Normal file
@ -0,0 +1,143 @@
|
||||
import 'package:anyhow/anyhow.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift_flutter/drift_flutter.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'database.g.dart';
|
||||
|
||||
@riverpod
|
||||
class NConnectedDevices extends _$NConnectedDevices {
|
||||
@override
|
||||
Future<List<ConnectedDevice>> build() async {
|
||||
final db = await ref.watch(databaseProvider);
|
||||
return await db.getAllConnectedDevices();
|
||||
}
|
||||
|
||||
Future<Result<int>> addConnectedDevice(
|
||||
ConnectedDevicesCompanion device) async {
|
||||
final db = await ref.watch(databaseProvider);
|
||||
final res = await db.addConnectedDevice(device);
|
||||
if (res.isOk()) {
|
||||
ref.invalidateSelf();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Future<Result<void>> deleteConnectedDevice(int id) async {
|
||||
final db = await ref.watch(databaseProvider);
|
||||
final res = await db.deleteConnectedDevice(id);
|
||||
if (res.isOk()) {
|
||||
ref.invalidateSelf();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/// Provider for the [AppDatabase] instance
|
||||
final databaseProvider = Provider<AppDatabase>((ref) {
|
||||
final database = AppDatabase();
|
||||
ref.onDispose(() => database.close());
|
||||
return database;
|
||||
});
|
||||
|
||||
/// Provider for all connected devices as a stream
|
||||
final connectedDevicesStreamProvider =
|
||||
StreamProvider<List<ConnectedDevice>>((ref) {
|
||||
final database = ref.watch(databaseProvider);
|
||||
return database.getAllConnectedDevicesStream();
|
||||
});
|
||||
|
||||
/// Provider for all connected devices as a future
|
||||
final connectedDevicesProvider = FutureProvider<List<ConnectedDevice>>((ref) {
|
||||
final database = ref.watch(databaseProvider);
|
||||
return database.getAllConnectedDevices();
|
||||
});
|
||||
|
||||
class ConnectedDevices extends Table {
|
||||
IntColumn get id => integer().autoIncrement()();
|
||||
TextColumn get deviceName => text()();
|
||||
TextColumn get deviceAddress => text()();
|
||||
TextColumn get deviceType => text()();
|
||||
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
|
||||
DateTimeColumn get lastConnectedAt => dateTime().nullable()();
|
||||
}
|
||||
|
||||
@DriftDatabase(tables: [ConnectedDevices])
|
||||
class AppDatabase extends _$AppDatabase {
|
||||
// After generating code, this class needs to define a `schemaVersion` getter
|
||||
// and a constructor telling drift where the database should be stored.
|
||||
// These are described in the getting started guide: https://drift.simonbinder.eu/setup/
|
||||
AppDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection());
|
||||
|
||||
@override
|
||||
int get schemaVersion => 1;
|
||||
|
||||
static QueryExecutor _openConnection() {
|
||||
return driftDatabase(
|
||||
name: 'my_database',
|
||||
native: const DriftNativeOptions(
|
||||
// By default, `driftDatabase` from `package:drift_flutter` stores the
|
||||
// database files in `getApplicationDocumentsDirectory()`.
|
||||
databaseDirectory: getApplicationSupportDirectory,
|
||||
),
|
||||
// If you need web support, see https://drift.simonbinder.eu/platforms/web/
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<ConnectedDevice>> getAllConnectedDevices() {
|
||||
return select(connectedDevices).get();
|
||||
}
|
||||
|
||||
/// Adds a new connected device to the database.
|
||||
///
|
||||
/// [device] is a [ConnectedDevicesCompanion] representing the device to be inserted.
|
||||
///
|
||||
/// Returns a [Result] indicating success or failure of the device insertion.
|
||||
/// On successful insertion, returns [Ok]\(rowid\). On failure, returns an error with a descriptive message.
|
||||
Future<Result<int>> addConnectedDevice(
|
||||
ConnectedDevicesCompanion device) async {
|
||||
try {
|
||||
if (!device.deviceAddress.present) {
|
||||
return bail('Device address is required to save a connected device.');
|
||||
}
|
||||
|
||||
final exists = await (select(connectedDevices)
|
||||
..where(
|
||||
(tbl) => tbl.deviceAddress.equals(device.deviceAddress.value)))
|
||||
.getSingleOrNull();
|
||||
if (exists != null) {
|
||||
return bail('Device ${device.deviceAddress.value} is already added.');
|
||||
}
|
||||
|
||||
final rowid = await into(connectedDevices).insert(device);
|
||||
return Ok(rowid);
|
||||
} catch (e, st) {
|
||||
return bail('Failed to add device: $e', st);
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes a connected device from the database by its ID.
|
||||
///
|
||||
/// [id] is the ID of the device to be deleted.
|
||||
///
|
||||
/// Returns a [Result] indicating success or failure of the deletion.
|
||||
/// On successful deletion, returns [Ok](number of deleted rows). On failure, returns an error with a descriptive message.
|
||||
Future<Result<void>> deleteConnectedDevice(int id) async {
|
||||
try {
|
||||
final count = await (delete(connectedDevices)
|
||||
..where((tbl) => tbl.id.equals(id)))
|
||||
.go();
|
||||
if (count == 0) {
|
||||
return bail('Device with id $id not found.');
|
||||
}
|
||||
return Ok(());
|
||||
} catch (e, st) {
|
||||
return bail('Failed to delete device with id $id: $e', st);
|
||||
}
|
||||
}
|
||||
|
||||
Stream<List<ConnectedDevice>> getAllConnectedDevicesStream() {
|
||||
return select(connectedDevices).watch();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user