Commit 551aca4
Changed files (3)
lib
model
lib/model/storage/db/config_dao.dart
@@ -0,0 +1,53 @@
+import 'package:blood_pressure_app/model/storage/db/config_db.dart';
+import 'package:blood_pressure_app/model/storage/settings_store.dart';
+import 'package:sqflite/sqflite.dart';
+
+class ConfigDao {
+ ConfigDao(this._configDB);
+
+ final ConfigDB _configDB;
+
+ /// Loads the profiles [Settings] object from the database.
+ ///
+ /// If any errors occur or the object is not present, a default one will be created. Changes in the object
+ /// will save to the database automatically (a listener gets attached).
+ Future<Settings> loadSettings(int profileID) async {
+ final dbEntry = await _configDB.database.query(
+ ConfigDB.settingsTable,
+ columns: ['settings_json'],
+ where: 'profile_id = ?',
+ whereArgs: [profileID]
+ );
+
+ late final Settings settings;
+ if (dbEntry.isEmpty) {
+ settings = Settings();
+ } else {
+ assert(dbEntry.length == 1, 'The profile_id should be unique.');
+ final settingsJson = dbEntry.first['settings_json'];
+ if (settingsJson == null) {
+ settings = Settings();
+ } else {
+ settings = Settings.fromJson(settingsJson.toString());
+ }
+ }
+ settings.addListener(() {
+ _updateSettings(profileID, settings);
+ });
+ return settings;
+ }
+
+ /// Update settings for a profile in the database.
+ ///
+ /// Adds an entry if necessary.
+ Future<void> _updateSettings(int profileID, Settings settings) async {
+ await _configDB.database.insert(
+ ConfigDB.settingsTable,
+ {
+ 'profile_id': profileID,
+ 'settings_json': settings.toJson()
+ },
+ conflictAlgorithm: ConflictAlgorithm.replace
+ );
+ }
+}
\ No newline at end of file
lib/model/storage/config_db.dart → lib/model/storage/db/config_db.dart
@@ -12,6 +12,23 @@ import 'package:sqflite/sqflite.dart';
/// internalColumnName STRING PRIMARY KEY, columnTitle STRING, formatPattern STRING
class ConfigDB {
ConfigDB._create();
+
+ /// Name of the settings table.
+ ///
+ /// It is used to store json representations of [Settings] objects.
+ ///
+ /// Format:
+ /// `CREATE TABLE settings(profile_id: INTEGER PRIMARY KEY, settings_json: STRING)`
+ static const String settingsTable = 'settings';
+ // instead of just changing this string when changing the format, _onDBUpgrade should be used.
+ static const String _settingsTableCreationString =
+ 'CREATE TABLE settings(profile_id: INTEGER PRIMARY KEY, settings_json: STRING)';
+
+ /// Name of the exportStrings table. It is used to store formats used in the [ExportConfigurationModel].
+ static const String exportStrings = 'exportStrings';
+ // instead of just changing this string when changing the format, _onDBUpgrade should be used.
+ static const String _exportStringsTableCreationString =
+ 'CREATE TABLE exportStrings(internalColumnName STRING PRIMARY KEY, columnTitle STRING, formatPattern STRING)';
late final Database _database;
@@ -32,16 +49,15 @@ class ConfigDB {
}
FutureOr<void> _onDBCreate(Database db, int version) {
- db.execute(
- 'CREATE TABLE exportStrings(internalColumnName STRING PRIMARY KEY, columnTitle STRING, formatPattern STRING)');
- db.execute('CREATE TABLE settings(profile_id: INTEGER PRIMARY KEY, settings_json: STRING)');
+ db.execute(_exportStringsTableCreationString);
+ db.execute(_settingsTableCreationString);
}
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('CREATE TABLE settings(profile_id: INTEGER PRIMARY KEY, settings_json: STRING)');
+ db.execute(_settingsTableCreationString);
db.database.setVersion(2);
} else {
assert(false, 'Unexpected version upgrade from $oldVersion to $newVersion.');
lib/model/storage/settings_store.dart
@@ -17,7 +17,7 @@ import 'package:flutter/material.dart';
class Settings extends ChangeNotifier {
/// Creates a settings object with the default values.
///
- /// Should only be called directly by tests and from factory methods.
+ /// When the values should be set consider using the factory methods.
Settings({
MaterialColor? accentColor,
MaterialColor? sysColor,