Commit 38aeb86

derdilla <derdilla06@gmail.com>
2023-05-13 08:42:57
use shared preferences for storing settings This simplifies the code drastically.
1 parent 966aa35
lib/model/settings.dart
@@ -1,103 +1,18 @@
-
-import 'dart:io';
-
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
-import 'package:path/path.dart';
-import 'package:sqflite_common_ffi/sqflite_ffi.dart';
-import 'package:sqflite/sqflite.dart';
+import 'package:shared_preferences/shared_preferences.dart';
 
 class Settings extends ChangeNotifier {
-  static const maxEntries = 2E64; // https://www.sqlite.org/limits.html Nr.13
-  late final Database _database;
-
-  late int _graphStepSize;
-  late DateTime _graphStart;
-  late DateTime _graphEnd;
-  late bool _followSystemDarkMode;
-  late bool _darkMode;
-  late MaterialColor _accentColor;
-  late MaterialColor _sysColor;
-  late MaterialColor _diaColor;
-  late MaterialColor _pulColor;
-  late bool _allowManualTimeInput;
-  late String _dateFormatString;
-  late bool _useExportCompatability;
+  late final SharedPreferences _prefs;
 
   Settings._create();
-  Future<void> _asyncInit(String? dbPath) async {
-    dbPath ??= await getDatabasesPath();
-
-    _database = await openDatabase(
-      join(dbPath, 'settings.db'),
-      // runs when the database is first created
-      onCreate: (db, version) {
-        return db.execute('CREATE TABLE settings(key STRING PRIMARY KEY, value STRING)');
-      },
-      version: 1,
-    );
-    await _loadSettings();
-  }
   // factory method, to allow for async contructor
-  static Future<Settings> create({String? dbPath}) async {
-    if (Platform.isWindows || Platform.isLinux) {
-      // Initialize FFI
-      sqfliteFfiInit();
-      // Change the default factory
-      databaseFactory = databaseFactoryFfi;
-    }
-
+  static Future<Settings> create() async {
     final component = Settings._create();
-    await component._asyncInit(dbPath);
+    component._prefs = await SharedPreferences.getInstance();
     return component;
   }
 
-  Future<Object?> _getSetting(String key) async {
-    final r = await _database.query('settings', where: 'key = ?', whereArgs: [key]);
-    if (r.isNotEmpty) {
-      return r[0]['value'];
-    }
-  }
-
-  Future<void> _saveSetting(String key, Object value) async {
-    if ((await _database.query('settings', where: 'key = ?', whereArgs: [key])).isEmpty) {
-      _database.insert('settings', {'key': key, 'value': value});
-    } else {
-      _database.update('settings', {'value': value}, where: 'key = ?', whereArgs: [key]);
-    }
-  }
-
-  Future<void> _loadSettings() async {
-    var pGraphStepSize = _getSetting('_graphStepSize');
-    var pGraphStart = _getSetting('_graphStart');
-    var pGraphEnd = _getSetting('_graphEnd');
-    var pFollowSystemDarkMode = _getSetting('_followSystemDarkMode');
-    var pDarkMode = _getSetting('_darkMode');
-    var pAccentColor = _getSetting('_accentColor');
-    var pSysColor = _getSetting('_sysColor');
-    var pDiaColor = _getSetting('_diaColor');
-    var pPulColor = _getSetting('_pulColor');
-    var pAllowManualTimeInput = _getSetting('_allowManualTimeInput');
-    var pDateFormatString = _getSetting('_dateFormatString');
-    var pUseExportCompatability = _getSetting('_useExportCompatability');
-    // var ...
-
-    _graphStepSize = (await pGraphStepSize as int?) ?? TimeStep.day;
-    _graphStart = DateTime.fromMillisecondsSinceEpoch((await pGraphStart as int?) ?? -1);
-    _graphEnd = DateTime.fromMillisecondsSinceEpoch((await pGraphEnd as int?) ?? -1);
-    _followSystemDarkMode = ((await pFollowSystemDarkMode as int?) ?? 1) == 1;
-    _darkMode = ((await pDarkMode as int?) ?? 1) == 1 ? true : false;
-    _accentColor = createMaterialColor(await pAccentColor as int? ?? 0xFF009688);
-    _sysColor = createMaterialColor(await pSysColor as int? ?? 0xFF009688);
-    _diaColor = createMaterialColor(await pDiaColor as int? ?? 0xFF4CAF50);
-    _pulColor = createMaterialColor(await pPulColor as int? ?? 0xFFF44336);
-    _allowManualTimeInput = ((await pAllowManualTimeInput as int?) ?? 1) == 1;
-    _dateFormatString = (await pDateFormatString as String?) ?? 'yy-MM-dd H:mm';
-    _useExportCompatability = ((await pUseExportCompatability as int?) ?? 0) == 1;
-    // ...
-    return;
-  }
-
   MaterialColor createMaterialColor(int value) {
     final color = Color(value);
     List strengths = <double>[.05];
@@ -120,101 +35,89 @@ class Settings extends ChangeNotifier {
   }
 
   int get graphStepSize {
-    return _graphStepSize;
+    return _prefs.getInt('graphStepSize') ?? TimeStep.day;
   }
   set graphStepSize(int newStepSize) {
-    _graphStepSize = newStepSize;
-    _saveSetting('_graphStepSize', newStepSize);
+    _prefs.setInt('graphStepSize', newStepSize);
     notifyListeners();
   }
 
   DateTime get graphStart {
-    return _graphStart;
+    return DateTime.fromMillisecondsSinceEpoch(_prefs.getInt('graphStart') ?? -1);
   }
   set graphStart(DateTime newGraphStart) {
-    _graphStart = newGraphStart;
-    _saveSetting('_graphStart', newGraphStart.millisecondsSinceEpoch);
+    _prefs.setInt('graphStart', newGraphStart.millisecondsSinceEpoch);
     notifyListeners();
   }
 
   DateTime get graphEnd {
-    return _graphEnd;
+    return DateTime.fromMillisecondsSinceEpoch(_prefs.getInt('graphEnd') ?? -1);
   }
   set graphEnd(DateTime newGraphEnd) {
-    _graphEnd = newGraphEnd;
-    _saveSetting('_graphEnd', newGraphEnd.millisecondsSinceEpoch);
+    _prefs.setInt('graphEnd', newGraphEnd.millisecondsSinceEpoch);
     notifyListeners();
   }
   bool get followSystemDarkMode {
-    return _followSystemDarkMode;
+    return _prefs.getBool('followSystemDarkMode') ?? true;
   }
   set followSystemDarkMode(bool newSetting) {
-    _followSystemDarkMode = newSetting;
-    _saveSetting('_followSystemDarkMode', newSetting ? "1" : "0");
+    _prefs.setBool('followSystemDarkMode', newSetting);
     notifyListeners();
   }
   bool get darkMode {
-    return _darkMode;
+    return _prefs.getBool('darkMode') ?? true;
   }
   set darkMode(bool newSetting) {
-    _darkMode = newSetting;
-    _saveSetting('_darkMode', newSetting ? 1 : 0);
+    _prefs.setBool('darkMode', newSetting);
     notifyListeners();
   }
   MaterialColor get accentColor {
-    return _accentColor;
+    return createMaterialColor(_prefs.getInt('accentColor') ?? 0xFF009688);
   }
   set accentColor(MaterialColor newColor) {
-    _accentColor = newColor;
-    _saveSetting('_accentColor', newColor.value);
+    _prefs.setInt('accentColor', newColor.value);
     notifyListeners();
   }
   MaterialColor get diaColor {
-    return _diaColor;
+    return createMaterialColor(_prefs.getInt('diaColor') ?? 0xFF4CAF50);
   }
   set diaColor(MaterialColor newColor) {
-    _diaColor = newColor;
-    _saveSetting('_diaColor', newColor.value);
+    _prefs.setInt('diaColor', newColor.value);
     notifyListeners();
   }
   MaterialColor get sysColor {
-    return _sysColor;
+    return createMaterialColor(_prefs.getInt('sysColor') ?? 0xFF009688);
   }
   set sysColor(MaterialColor newColor) {
-    _sysColor = newColor;
-    _saveSetting('_sysColor', newColor.value);
+    _prefs.setInt('sysColor', newColor.value);
     notifyListeners();
   }
   MaterialColor get pulColor {
-    return _pulColor;
+    return createMaterialColor(_prefs.getInt('pulColor') ?? 0xFFF44336);
   }
   set pulColor(MaterialColor newColor) {
-    _pulColor = newColor;
-    _saveSetting('_pulColor', newColor.value);
+    _prefs.setInt('pulColor', newColor.value);
     notifyListeners();
   }
   bool get allowManualTimeInput {
-    return _allowManualTimeInput;
+    return _prefs.getBool('allowManualTimeInput') ?? true;
   }
   set allowManualTimeInput(bool newSetting) {
-    _allowManualTimeInput = newSetting;
-    _saveSetting('_allowManualTimeInput', newSetting ? 1 : 0);
+    _prefs.setBool('allowManualTimeInput', newSetting);
     notifyListeners();
   }
   String get dateFormatString {
-    return _dateFormatString;
+    return _prefs.getString('dateFormatString') ?? 'yy-MM-dd H:mm';
   }
   set dateFormatString(String newFormatString) {
-    _dateFormatString = newFormatString;
-    _saveSetting('_dateFormatString', newFormatString);
+    _prefs.setString('dateFormatString', newFormatString);
     notifyListeners();
   }
   bool get useExportCompatability {
-    return _useExportCompatability;
+    return _prefs.getBool('useExportCompatability') ?? false;
   }
   set useExportCompatability(bool useExportCompatability) {
-    _useExportCompatability = useExportCompatability;
-    _saveSetting('_useExportCompatability', useExportCompatability);
+    _prefs.setBool('useExportCompatability', useExportCompatability);
     notifyListeners();
   }
 
lib/screens/home.dart
@@ -3,28 +3,26 @@ import 'package:blood_pressure_app/screens/settings.dart';
 import 'package:flutter/material.dart';
 import 'package:blood_pressure_app/components/measurement_graph.dart';
 import 'package:blood_pressure_app/components/measurement_list.dart';
-import 'package:provider/provider.dart';
-import 'package:blood_pressure_app/model/blood_pressure.dart';
 
 class AppHome extends StatelessWidget {
   const AppHome({super.key});
 
   @override
   Widget build(BuildContext context) {
-    var _padding;
+    EdgeInsets padding;
     if (MediaQuery.of(context).size.width < 1000) {
-      _padding = const EdgeInsets.only(left: 10, right: 10, bottom: 15, top: 30);
+      padding = const EdgeInsets.only(left: 10, right: 10, bottom: 15, top: 30);
     } else {
-      _padding = const EdgeInsets.all(80);
+      padding = const EdgeInsets.all(80);
     }
 
     return Scaffold(
       body: Center(
         child: Container(
-          padding: _padding,
+          padding: padding,
           child: Column(
             children: [
-              MeasurementGraph(),
+              const MeasurementGraph(),
               Expanded(
                 flex: 50,
                   child: MeasurementList(context)
@@ -71,7 +69,7 @@ class AppHome extends StatelessWidget {
                   onPressed: () {
                     Navigator.push(
                       context,
-                      MaterialPageRoute(builder: (context) => const SettingsScreen()),
+                      MaterialPageRoute(builder: (context) => const SettingsPage()),
                     );
                   },
                 ),
lib/screens/settings.dart
@@ -5,8 +5,8 @@ import 'package:blood_pressure_app/screens/enter_timeformat.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 
-class SettingsScreen extends StatelessWidget {
-  const SettingsScreen({super.key});
+class SettingsPage extends StatelessWidget {
+  const SettingsPage({super.key});
 
   @override
   Widget build(BuildContext context) {
macos/Flutter/GeneratedPluginRegistrant.swift
@@ -8,6 +8,7 @@ import Foundation
 import file_saver
 import path_provider_foundation
 import share_plus_macos
+import shared_preferences_foundation
 import sqflite
 import url_launcher_macos
 
@@ -15,6 +16,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
   FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin"))
   PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
   SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
+  SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
   SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
   UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
 }
test/model/bood_pressure_test.dart
@@ -58,8 +58,7 @@ void main() {
       await m.add(BloodPressureRecord(DateTime.fromMillisecondsSinceEpoch(1), 0, 0, 0, ''));
       await m.add(BloodPressureRecord(DateTime.fromMillisecondsSinceEpoch(2), 0, 0, 0, ''));
 
-      print(listenerCalls);
-      expect(listenerCalls, 3); // TODO: FAILS
+      expect(listenerCalls, 3);
     });
 
     test('should return entries as added', () async {
test/model/settings_test.dart
@@ -1,8 +1,12 @@
 import 'package:blood_pressure_app/model/settings.dart';
 import 'package:flutter_test/flutter_test.dart';
+import 'package:shared_preferences/shared_preferences.dart';
 import 'package:sqflite_common_ffi/sqflite_ffi.dart';
 
 void main() {
+  TestWidgetsFlutterBinding.ensureInitialized();
+  SharedPreferences.setMockInitialValues({});
+
   group('TimeStep', () {
     test('names should match to fields', () {
       expect(TimeStep.getName(TimeStep.day), 'day');
pubspec.lock
@@ -440,6 +440,62 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "3.0.1"
+  shared_preferences:
+    dependency: "direct main"
+    description:
+      name: shared_preferences
+      sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.1"
+  shared_preferences_android:
+    dependency: transitive
+    description:
+      name: shared_preferences_android
+      sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.4"
+  shared_preferences_foundation:
+    dependency: transitive
+    description:
+      name: shared_preferences_foundation
+      sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.2"
+  shared_preferences_linux:
+    dependency: transitive
+    description:
+      name: shared_preferences_linux
+      sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.0"
+  shared_preferences_platform_interface:
+    dependency: transitive
+    description:
+      name: shared_preferences_platform_interface
+      sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.0"
+  shared_preferences_web:
+    dependency: transitive
+    description:
+      name: shared_preferences_web
+      sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.0"
+  shared_preferences_windows:
+    dependency: transitive
+    description:
+      name: shared_preferences_windows
+      sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.2.0"
   sky_engine:
     dependency: transitive
     description: flutter
pubspec.yaml
@@ -42,6 +42,7 @@ dependencies:
   file_picker: ^5.2.11  # MIT
   csv: ^5.0.2  # MIT
   url_launcher: ^6.1.10  # BSD-3-Clause
+  shared_preferences: ^2.1.1  # BSD-3-Clause
 
 dev_dependencies:
   flutter_test: