Commit e9b6b53

derdilla <derdilla06@gmail.com>
2023-09-12 15:09:35
safe needle pin in BloodPressureModel database
1 parent c2e7b6e
Changed files (1)
lib/model/blood_pressure.dart
@@ -1,3 +1,5 @@
+import 'dart:async';
+import 'dart:convert';
 import 'dart:io';
 
 import 'package:blood_pressure_app/screens/error_reporting.dart';
@@ -18,25 +20,46 @@ class BloodPressureModel extends ChangeNotifier {
       dbPath = join(dbPath, 'blood_pressure.db');
     }
 
+    // In case safer data loading is needed: finish this.
+    /*
+    String? backupPath;
+    if (dbPath != inMemoryDatabasePath) {
+      assert(_database.isUndefinedOrNull);
+      backupPath = join(Directory.systemTemp.path, 'blood_pressure_bu_${DateTime.now().millisecondsSinceEpoch}.db');
+      final copiedFile = File(dbPath).copy(backupPath);
+      copiedFile.onError((error, stackTrace) => null)
+    }
+    var preserveBackup = false;
+    */
+
     _database = await openDatabase(
       dbPath,
       // runs when the database is first created
-      onCreate: (db, version) {
-        return db.execute(
-            'CREATE TABLE bloodPressureModel(timestamp INTEGER(14) PRIMARY KEY, systolic INTEGER, diastolic INTEGER, pulse INTEGER, notes STRING)');
-      },
-      onUpgrade: (db, oldVersion, newVersion) async {
-        if (oldVersion == 1 && newVersion == 2) {
-          // TODO
-        } else {
-          await ErrorReporting.reportCriticalError('Unsupported database upgrade', 'Attempted to upgrade the measurement database from version $oldVersion to version $newVersion, which is not supported. This action failed to avoid data loss. Please contact the app developer by opening an issue with the link below or writing an email to contact@derdilla.com.');
-          // TODO: error, open emergency page
-        }
-      },
-      version: 1,
+      onCreate: _onDVCreate,
+      onUpgrade: _onDBUpgrade,
+      version: 2,
     );
   }
 
+  FutureOr<void> _onDVCreate(Database db, int version) {
+      return db.execute('CREATE TABLE bloodPressureModel('
+          'timestamp INTEGER(14) PRIMARY KEY,'
+          'systolic INTEGER, diastolic INTEGER,'
+          'pulse INTEGER,'
+          'notes STRING,'
+          'needlePin STRING)');
+    }
+
+  FutureOr<void> _onDBUpgrade(Database db, int oldVersion, int newVersion) async {
+    // When adding more versions the upgrade procedure proposed in https://stackoverflow.com/a/75153875/21489239
+    // might be useful, to avoid duplicated code. Currently this would only lead to complexity, without benefits.
+    if (oldVersion == 1 && newVersion == 2) {
+      db.execute('ALTER TABLE bloodPressureModel ADD COLUMN needlePin STRING;');
+    } else {
+      await ErrorReporting.reportCriticalError('Unsupported database upgrade', 'Attempted to upgrade the measurement database from version $oldVersion to version $newVersion, which is not supported. This action failed to avoid data loss. Please contact the app developer by opening an issue with the link below or writing an email to contact@derdilla.com.');
+    }
+  }
+
   // factory method, to allow for async constructor
   static Future<BloodPressureModel> create({String? dbPath, bool isFullPath = false}) async {
     if (Platform.isWindows || Platform.isLinux) {
@@ -60,7 +83,8 @@ class BloodPressureModel extends ChangeNotifier {
             'systolic': measurement.systolic,
             'diastolic': measurement.diastolic,
             'pulse': measurement.pulse,
-            'notes': measurement.notes
+            'notes': measurement.notes,
+            'needlePin': jsonEncode(measurement.needlePin)
           },
           where: 'timestamp = ?',
           whereArgs: [measurement.creationTime.millisecondsSinceEpoch]);
@@ -70,7 +94,8 @@ class BloodPressureModel extends ChangeNotifier {
         'systolic': measurement.systolic,
         'diastolic': measurement.diastolic,
         'pulse': measurement.pulse,
-        'notes': measurement.notes
+        'notes': measurement.notes,
+        'needlePin': jsonEncode(measurement.needlePin)
       });
     }
     notifyListeners();
@@ -102,8 +127,15 @@ class BloodPressureModel extends ChangeNotifier {
   List<BloodPressureRecord> _convert(List<Map<String, Object?>> dbResult) {
     List<BloodPressureRecord> records = [];
     for (var e in dbResult) {
-      records.add(BloodPressureRecord(DateTime.fromMillisecondsSinceEpoch(e['timestamp'] as int), e['systolic'] as int?,
-          e['diastolic'] as int?, e['pulse'] as int?, e['notes'].toString()));
+      final needlePinJson = e['needlePin'] as String?;
+      records.add(BloodPressureRecord(
+        DateTime.fromMillisecondsSinceEpoch(e['timestamp'] as int),
+        e['systolic'] as int?,
+        e['diastolic'] as int?,
+        e['pulse'] as int?,
+        e['notes'].toString(),
+        needlePin: (needlePinJson == null) ? null : jsonDecode(needlePinJson) as MeasurementNeedlePin
+      ));
     }
     return records;
   }
@@ -150,6 +182,12 @@ class MeasurementNeedlePin {
   final Color color;
 
   const MeasurementNeedlePin(this.color);
+  // When updating this, remember to be backwards compatible
+  MeasurementNeedlePin.fromJson(Map<String, dynamic> json)
+      : color = Color(json['color']);
+  Map<String, dynamic> toJson() => {
+    'color': color.value,
+  };
 }
 
 // source: https://pressbooks.library.torontomu.ca/vitalsign/chapter/blood-pressure-ranges/ (last access: 20.05.2023)