Commit 977adf4

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2024-03-07 16:39:09
make feature "functional"
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent 669ac39
Changed files (5)
lib/model/blood_pressure/model.dart
@@ -77,8 +77,8 @@ class BloodPressureModel extends ChangeNotifier {
 
   /// Adds a new measurement at the correct chronological position in the List.
   ///
-  /// This is not suitable for user inputs, as in this case export is needed as well. Consider using
-  /// [BloodPressureModel.addAndExport] instead.
+  /// This is not suitable for user inputs, as in this case export is needed as
+  /// well. Consider using [BloodPressureModel.addAndExport] instead.
   Future<void> add(BloodPressureRecord measurement) async {
     if (!_database.isOpen) return;
     final existing = await _database.query('bloodPressureModel',
@@ -108,6 +108,26 @@ class BloodPressureModel extends ChangeNotifier {
     notifyListeners();
   }
 
+  /// Convenience wrapper for [add] that follows best practices.
+  ///
+  /// This ensures no timeout occurs by waiting for operations to finish and
+  /// exports in case the [context] is provided and the option in export
+  /// settings is active.
+  Future<void> addAll(
+    List<BloodPressureRecord> measurements,
+    BuildContext? context,
+  ) async {
+    for (final measurement in measurements) {
+      await add(measurement);
+    }
+
+    if (context == null || !context.mounted) return;
+    final exportSettings = Provider.of<ExportSettings>(context, listen: false);
+    if (exportSettings.exportAfterEveryEntry) {
+      performExport(context);
+    }
+  }
+
   /// Adds a measurement to the model and tries to export all measurements, if [ExportSettings.exportAfterEveryEntry] is
   /// true.
   Future<void> addAndExport(BuildContext context, BloodPressureRecord record) async {
lib/screens/subsettings/export_import/export_button_bar.dart
@@ -97,18 +97,14 @@ class ExportButtonBar extends StatelessWidget {
                     });
                     if (result.hasError()) return;
                     final model = Provider.of<BloodPressureModel>(context, listen: false);
-                    for (final record in importedRecords) {
-                      await model.add(record);
-                    }
+                    await model.addAll(importedRecords, null);
                     messenger.showSnackBar(SnackBar(content: Text(
                         localizations.importSuccess(importedRecords.length),),),);
                     break;
                   case 'db':
                     final model = Provider.of<BloodPressureModel>(context, listen: false);
                     final importedModel = await BloodPressureModel.create(dbPath: file.path, isFullPath: true);
-                    for (final record in await importedModel.all) {
-                      await model.add(record);
-                    }
+                    await model.addAll(await importedModel.all, null);
                     break;
                   default:
                     _showError(messenger, localizations.errWrongImportFormat);
lib/screens/subsettings/foreign_db_import_screen.dart
@@ -16,11 +16,20 @@ import 'package:sqflite/sqflite.dart';
 /// Parses data table to [BloodPressureRecord] list.
 class ForeignDBImportScreen extends StatefulWidget {
   /// Create a screen to import data from a database with unknown structure.
-  const ForeignDBImportScreen({super.key, required this.db});
+  /// 
+  /// Parses selected data to a [BloodPressureRecord] list.
+  const ForeignDBImportScreen({super.key, 
+    required this.db, 
+    required this.bottomAppBars,
+  });
 
   /// Database from which to import data.
   final Database db;
 
+  /// Whether to move the app bar for saving and loading to the bottom of the
+  /// screen.
+  final bool bottomAppBars;
+
   @override
   State<ForeignDBImportScreen> createState() => _ForeignDBImportScreenState();
 }
@@ -60,7 +69,8 @@ class _ForeignDBImportScreenState extends State<ForeignDBImportScreen> {
           }
           if (elements.length < 4) return 'Select at least one data column';
 
-          return 'The schnibledumps doesn\'t schwibble!'; // TODO
+          // return 'The schnibledumps doesn\'t schwibble!'; // TODO check if more tests are required
+          return null;
         },
         onSaved: (List<String> madeSelections) async {
           final tableName = madeSelections.removeAt(0);
@@ -126,7 +136,7 @@ class _ForeignDBImportScreenState extends State<ForeignDBImportScreen> {
             return 'Select column type (${selections.last})';
           }
         },
-        bottomAppBars: true, // TODO
+        bottomAppBars: widget.bottomAppBars, // TODO
       );
       // TODO: localize everything
       // TODO: detect when no more selections are possible
@@ -177,3 +187,18 @@ class _ColumnImportData {
   /// Names of all tables.
   Iterable<String> get tableNames => columns.keys;
 }
+
+/// Shows a dialoge to import arbitrary data from a external database.
+Future<List<BloodPressureRecord>?> showForeignDBImportDialoge(
+    BuildContext context,
+    bool bottomAppBars,
+    Database db) =>
+    showDialog<List<BloodPressureRecord>>(
+      context: context, builder: (context) =>
+        Dialog.fullscreen(
+          child: ForeignDBImportScreen(
+            bottomAppBars: bottomAppBars,
+            db: db,
+          ),
+        ),
+    );
lib/screens/settings_screen.dart
@@ -4,6 +4,7 @@ import 'package:blood_pressure_app/components/consistent_future_builder.dart';
 import 'package:blood_pressure_app/components/dialoges/enter_timeformat_dialoge.dart';
 import 'package:blood_pressure_app/components/dialoges/input_dialoge.dart';
 import 'package:blood_pressure_app/components/settings/settings_widgets.dart';
+import 'package:blood_pressure_app/model/blood_pressure/model.dart';
 import 'package:blood_pressure_app/model/blood_pressure/warn_values.dart';
 import 'package:blood_pressure_app/model/iso_lang_names.dart';
 import 'package:blood_pressure_app/model/storage/storage.dart';
@@ -341,11 +342,13 @@ class SettingsPage extends StatelessWidget {
                     },
                 ),
                 ListTile(
-                  title: Text('TODO'), // TODO
-                  leading: Icon(Icons.add_circle, color: Colors.red,),
+                  title: Text('Import foreign database (Preview)'), // TODO
+                  subtitle: Text('Unstable feature: Use at your own risk. Please'
+                      ' open issues and give feedback in form of issues on this '
+                      'projects GitHub page (accessible through the source code button).'),
+                  leading: Icon(Icons.add_circle, color: Colors.orange,),
                   onTap: () async {
                     final messenger = ScaffoldMessenger.of(context);
-                    final navigator = Navigator.of(context);
                     final result = await FilePicker.platform.pickFiles();
 
                     if (result == null) {
@@ -360,9 +363,20 @@ class SettingsPage extends StatelessWidget {
 
                     final db = await openDatabase(path);
 
-                    navigator.push(MaterialPageRoute(builder: (context) =>
-                          ForeignDBImportScreen(db: db,),),
-                    );
+                    if (!context.mounted) return;
+                    final data = await showForeignDBImportDialoge(context,
+                        settings.bottomAppBars, db,);
+
+                    if (!context.mounted) return;
+                    if (data == null) {
+                      messenger.showSnackBar(SnackBar(content: Text(localizations.errNotImportable)));
+                      return;
+                    }
+                    // TODO: Show import preview
+                    final model = Provider.of<BloodPressureModel>(context, listen: false);
+                    await model.addAll(data, context);
+                    // TODO: give feedback
+
                   },
                 )
               ],
test/ram_only_implementations.dart
@@ -47,4 +47,11 @@ class RamBloodPressureModel extends ChangeNotifier implements BloodPressureModel
   Future<void> addAndExport(BuildContext context, BloodPressureRecord record) async {
     add(record);
   }
+
+  @override
+  Future<void> addAll(List<BloodPressureRecord> measurements, BuildContext? context) async {
+    for (final m in measurements) {
+      add(m);
+    }
+  }
 }