144 lines
4.8 KiB
Dart
144 lines
4.8 KiB
Dart
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();
|
|
}
|
|
}
|