Commit 4841240

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2024-06-11 19:58:46
update data deletion page to avoid restarts
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent e6d3e34
app/lib/l10n/app_en.arb
@@ -506,5 +506,7 @@
   "titleInCsv": "Title in CSV",
   "@titleInCsv": {},
   "preferredPressureUnit": "Preferred pressure unit",
-  "@preferredPressureUnit": {}
+  "@preferredPressureUnit": {},
+  "deleteAllMedicineIntakes": "Delete all medicine intakes",
+  "@deleteAllMedicineIntakes": {}
 }
app/lib/model/storage/export_columns_store.dart
@@ -42,6 +42,7 @@ class ExportColumnsManager extends ChangeNotifier {
   /// Reset all fields to their default values.
   void reset() {
     _userColumns.clear();
+    notifyListeners();
   }
 
   /// Namespaces that may not lead a user columns internal identifier.
app/lib/model/storage/export_csv_settings_store.dart
@@ -68,6 +68,7 @@ class CsvExportSettings extends ChangeNotifier implements CustomFieldsSettings {
     _textDelimiter = d._textDelimiter;
     _exportHeadline = d._exportHeadline;
     _exportFieldsConfiguration = d._exportFieldsConfiguration;
+    notifyListeners();
   }
 
   String _fieldDelimiter = ',';
app/lib/model/storage/export_pdf_settings_store.dart
@@ -74,6 +74,7 @@ class PdfExportSettings extends ChangeNotifier implements CustomFieldsSettings {
     _headerFontSize = d._headerFontSize;
     _cellFontSize = d._cellFontSize;
     _exportFieldsConfiguration = d._exportFieldsConfiguration;
+    notifyListeners();
   }
 
   bool _exportTitle = true;
app/lib/model/storage/export_settings_store.dart
@@ -43,6 +43,7 @@ class ExportSettings extends ChangeNotifier {
     _exportFormat = d._exportFormat;
     _defaultExportDir = d._defaultExportDir;
     _exportAfterEveryEntry = d._exportAfterEveryEntry;
+    notifyListeners();
   }
 
   ExportFormat _exportFormat = ExportFormat.csv;
app/lib/model/storage/intervall_store.dart
@@ -270,6 +270,7 @@ class IntervallStoreManager extends ChangeNotifier {
     mainPage = IntervallStorage();
     exportPage = IntervallStorage();
     statsPage = IntervallStorage();
+    notifyListeners();
   }
 
   /// Intervall for the page with graph and list.
app/lib/model/storage/settings_store.dart
@@ -181,6 +181,7 @@ class Settings extends ChangeNotifier {
     _medications.clear();
     _highestMedIndex = d._highestMedIndex;
     _preferredPressureUnit = d._preferredPressureUnit;
+    notifyListeners();
   }
 
   Locale? _language;
app/lib/screens/subsettings/delete_data_screen.dart
@@ -1,15 +1,12 @@
-import 'dart:io';
-import 'dart:math';
-
-import 'package:blood_pressure_app/components/consistent_future_builder.dart';
-import 'package:blood_pressure_app/components/custom_banner.dart';
-import 'package:blood_pressure_app/main.dart';
+import 'package:blood_pressure_app/model/blood_pressure/model.dart';
+import 'package:blood_pressure_app/model/storage/export_columns_store.dart';
+import 'package:blood_pressure_app/model/storage/storage.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
-import 'package:path/path.dart';
-import 'package:restart_app/restart_app.dart';
-import 'package:sqflite/sqflite.dart';
+import 'package:health_data_store/health_data_store.dart';
+import 'package:provider/provider.dart';
 
+/// Screen that allows
 class DeleteDataScreen extends StatefulWidget {
   const DeleteDataScreen({super.key});
 
@@ -18,11 +15,6 @@ class DeleteDataScreen extends StatefulWidget {
 }
 
 class _DeleteDataScreenState extends State<DeleteDataScreen> {
-  /// Whether or not files were deleted while on this page.
-  ///
-  /// Should never be reset to false.
-  bool _deletedData = false;
-
   @override
   Widget build(BuildContext context) {
     final localizations = AppLocalizations.of(context)!;
@@ -32,193 +24,98 @@ class _DeleteDataScreenState extends State<DeleteDataScreen> {
         leading: IconButton(
           icon: const Icon(Icons.arrow_back),
           onPressed: () {
-            if (_deletedData) {
-              Restart.restartApp();
-            } else {
-              Navigator.pop(context, );
-            }
+            Navigator.pop(context);
           },
         ),
       ),
-      body: Column(
+      body: ListView(
         children: [
-          if (_deletedData)
-            CustomBanner(
-                content: Text(localizations.warnNeedsRestartForUsingApp),
-                action: TextButton(
-                  onPressed: Restart.restartApp,
-                  child: Text(localizations.restartNow),
-                ),
-            ),
-          Expanded(
-            child: Container(
-              padding: const EdgeInsets.all(10),
-              child: Column(
-                mainAxisSize: MainAxisSize.min,
-                crossAxisAlignment: CrossAxisAlignment.start,
-                children: [
-                  Text(localizations.data, style: Theme.of(context).textTheme.headlineMedium),
-                  Expanded(
-                    child: ListView(
-                      children: [
-                        ListTile(
-                          leading: const Icon(Icons.timeline),
-                          title: Text(localizations.deleteAllMeasurements),
-                          subtitle: ConsistentFutureBuilder(
-                            future: Future(() async {
-                              final String dbPath = join(await getDatabasesPath(), 'blood_pressure.db');
-                              final String dbJournalPath = join(await getDatabasesPath(), 'blood_pressure.db-journal');
-                              int sizeBytes;
-                              try {
-                                sizeBytes = File(dbPath).lengthSync();
-                              } on PathNotFoundException {
-                                sizeBytes = 0;
-                              }
-                              try {
-                                sizeBytes += File(dbJournalPath).lengthSync();
-                              } on PathNotFoundException {}
-
-                              return _bytesToString(sizeBytes);
-                            }),
-                            onData: (context, data) => Text(data),
-                          ),
-                          trailing: const Icon(Icons.delete_forever),
-                          onTap: () async {
-                            final messanger = ScaffoldMessenger.of(context);
-                            if (await showDeleteDialoge(context, localizations)) {
-                            final String dbPath = join(await getDatabasesPath(), 'blood_pressure.db');
-                            final String dbJournalPath = join(await getDatabasesPath(), 'blood_pressure.db-journal');
-                            await closeDatabases();
-                            tryDeleteFile(dbPath, messanger, localizations);
-                            tryDeleteFile(dbJournalPath, messanger, localizations);
-                            setState(() {
-                            _deletedData = true;
-                            });
-                            }
-                          },
-                        ),
-                        ListTile(
-                          leading: const Icon(Icons.settings),
-                          title: Text(localizations.deleteAllSettings),
-                          subtitle: ConsistentFutureBuilder(
-                            future: Future(() async {
-                              final String dbPath = join(await getDatabasesPath(), 'config.db');
-                              final String dbJournalPath = join(await getDatabasesPath(), 'config.db-journal');
-                              int sizeBytes;
-                              try {
-                                sizeBytes = File(dbPath).lengthSync();
-                              } on PathNotFoundException {
-                                sizeBytes = 0;
-                              }
-                              try {
-                                sizeBytes += File(dbJournalPath).lengthSync();
-                              } on PathNotFoundException {}
-                              return _bytesToString(sizeBytes);
-                            }),
-                            onData: (context, data) => Text(data),
-                          ),
-                          trailing: const Icon(Icons.delete_forever),
-                          onTap: () async {
-                            final messanger = ScaffoldMessenger.of(context);
-                            if (await showDeleteDialoge(context, localizations)) {
-                              final String dbPath = join(await getDatabasesPath(), 'config.db');
-                              final String dbJournalPath = join(await getDatabasesPath(), 'config.db-journal');
-                              await closeDatabases();
-                              tryDeleteFile(dbPath, messanger, localizations);
-                              tryDeleteFile(dbJournalPath, messanger, localizations);
-                              setState(() {
-                                _deletedData = true;
-                              });
-                            }
-                          },
-                        ),
-                      ],
-                    ),
+          ListTile(
+            leading: const Icon(Icons.timeline),
+            title: Text(localizations.deleteAllMeasurements),
+            trailing: const Icon(Icons.delete_forever),
+            onTap: () async {
+              final messanger = ScaffoldMessenger.of(context);
+              if (await _showDeleteDialoge(context, localizations)) {
+                final model = context.read<BloodPressureModel>();
+                final previousRecords = await model.all;
+                for (final record in previousRecords) {
+                  await model.delete(record.creationTime);
+                }
+                messanger.showSnackBar(SnackBar(
+                  content: Text(localizations.deletionConfirmed),
+                  action: SnackBarAction(
+                    label: localizations.btnUndo,
+                    onPressed: () => model.addAll(previousRecords, context),
                   ),
-                  /* Text('Files', style: Theme.of(context).textTheme.headlineMedium),
-                  Expanded(
-                    flex: 3,
-                    child: ConsistentFutureBuilder(
-                      future: Future(() async => Directory(await getDatabasesPath()).list(recursive: true).toList()),
-                      onData: (context, files) =>
-                        ListView.builder(
-                          itemCount: files.length,
-                          itemBuilder: (context, idx) => ListTile(
-                            title: Text(files[idx].path),
-                            trailing: const Icon(Icons.delete_forever),
-                            onTap: () async {
-                              final messanger = ScaffoldMessenger.of(context);
-                              if (await showDeleteDialoge(context, localizations)) {
-                                if (!context.mounted) return;
-                                await unregisterAllProviders(context);
-                                files[idx].deleteSync();
-                                messanger.showSnackBar(SnackBar(
-                                  duration: const Duration(seconds: 5),
-                                  content: Text('File deleted.'),
-                                ));
-                                setState(() {
-                                  _deletedData = true;
-                                });
-                              }
-                            },
-                          )
-                        )
-                    ),
-                  ), */
-                ],
-              ),
-            ),
+                ));
+              }
+            },
+          ),
+          ListTile(
+            leading: const Icon(Icons.settings),
+            title: Text(localizations.deleteAllSettings),
+            trailing: const Icon(Icons.delete_forever),
+            onTap: () async {
+              final messanger = ScaffoldMessenger.of(context);
+              if (await _showDeleteDialoge(context, localizations)) {
+                context.read<Settings>().reset();
+                context.read<ExportSettings>().reset();
+                context.read<CsvExportSettings>().reset();
+                context.read<PdfExportSettings>().reset();
+                context.read<IntervallStoreManager>().reset();
+                context.read<ExportColumnsManager>().reset();
+                messanger.showSnackBar(SnackBar(
+                  content: Text(localizations.deletionConfirmed),
+                ));
+              }
+            },
+          ),
+          ListTile(
+            leading: const Icon(Icons.medication),
+            title: Text(localizations.deleteAllMedicineIntakes),
+            trailing: const Icon(Icons.delete_forever),
+            onTap: () async {
+              if (await _showDeleteDialoge(context, localizations)) {
+                final repo = context.read<MedicineIntakeRepository>();
+                final allIntakes = await repo.get(DateRange(start: DateTime.fromMillisecondsSinceEpoch(0), end: DateTime.now()));
+                for (final intake in allIntakes) {
+                  await repo.remove(intake);
+                }
+                final messanger = ScaffoldMessenger.of(context);
+                messanger.showSnackBar(SnackBar(
+                  content: Text(localizations.deletionConfirmed),
+                ));
+              }
+            },
           ),
         ],
       ),
     );
   }
 
-  /// Converts file size in bytes to human readable string
-  String _bytesToString(int sizeBytes) {
-    if (sizeBytes <= 0) return '0 B';
-    const suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
-    final i = (log(sizeBytes) / log(1024)).floor();
-    return '${(sizeBytes / pow(1024, i)).toStringAsFixed(1)} ${suffixes[i]}';
-  }
-
-  Future<bool> showDeleteDialoge(BuildContext context, AppLocalizations localizations) async => await showDialog<bool>(context: context, builder: (context) =>
-        AlertDialog(
-          title: Text(localizations.confirmDelete),
-          content: Text(localizations.warnDeletionUnrecoverable),
-          actionsAlignment: MainAxisAlignment.spaceBetween,
-          actions: [
-            TextButton(
-                onPressed: () => Navigator.pop(context, false),
-                child: Text(AppLocalizations.of(context)!.btnCancel),),
-            Theme(
-              data: ThemeData.from(
-                  colorScheme: ColorScheme.fromSeed(seedColor: Colors.red, brightness: Theme.of(context).brightness),
-                  useMaterial3: true,
-              ),
-              child: ElevatedButton.icon(
-                  onPressed: () => Navigator.pop(context, true),
-                  icon: const Icon(Icons.delete_forever),
-                  label: Text(AppLocalizations.of(context)!.btnConfirm),
-              ),
-            ),
-
-          ],
+  /// Show dialoge to confirm irrevocable deletion.
+  Future<bool> _showDeleteDialoge(BuildContext context, AppLocalizations localizations) async => await showDialog<bool>(context: context, builder: (context) =>
+    AlertDialog(
+      title: Text(localizations.confirmDelete),
+      content: Text(localizations.warnDeletionUnrecoverable),
+      actionsAlignment: MainAxisAlignment.spaceBetween,
+      actions: [
+        TextButton(
+            onPressed: () => Navigator.pop(context, false),
+            child: Text(AppLocalizations.of(context)!.btnCancel),),
+        Theme(
+          data: ThemeData.from(
+              colorScheme: ColorScheme.fromSeed(seedColor: Colors.red, brightness: Theme.of(context).brightness),
+              useMaterial3: true,
+          ),
+          child: ElevatedButton.icon(
+              onPressed: () => Navigator.pop(context, true),
+              icon: const Icon(Icons.delete_forever),
+              label: Text(AppLocalizations.of(context)!.btnConfirm),
+          ),
         ),
-    ) ?? false;
-  
-  void tryDeleteFile(String path, ScaffoldMessengerState messanger, AppLocalizations localizations) {
-    try {
-      File(path).deleteSync();
-      messanger.showSnackBar(SnackBar(
-        duration: const Duration(seconds: 2),
-        content: Text(localizations.fileDeleted),
-      ),);
-    } on PathNotFoundException {
-      messanger.showSnackBar(SnackBar(
-        duration: const Duration(seconds: 2),
-        content: Text(localizations.fileAlreadyDeleted),
-      ),);
-    }
-  }
-}
\ No newline at end of file
+      ],
+    ),
+  ) ?? false;
+}
app/lib/screens/settings_screen.dart
@@ -1,6 +1,7 @@
 import 'dart:io';
 
 import 'package:blood_pressure_app/components/consistent_future_builder.dart';
+import 'package:blood_pressure_app/components/custom_banner.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';
@@ -23,7 +24,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 import 'package:package_info_plus/package_info_plus.dart';
 import 'package:path/path.dart';
 import 'package:provider/provider.dart';
-import 'package:restart_app/restart_app.dart';
 import 'package:sqflite/sqflite.dart';
 import 'package:url_launcher/url_launcher.dart';
 
@@ -318,13 +318,10 @@ class SettingsPage extends StatelessWidget {
                     }
 
                     String dbPath = await getDatabasesPath();
-                    assert(dbPath != inMemoryDatabasePath);
                     dbPath = join(dbPath, 'config.db');
                     File(path).copySync(dbPath);
-                    if (!await Restart.restartApp()) {
-                      messenger.showSnackBar(SnackBar(content: Text(localizations.pleaseRestart)));
-                      return;
-                    }
+                    messenger.showMaterialBanner(CustomBanner(content: Text(localizations.pleaseRestart)));
+                    // TODO: read settings and replace them on running app.
                   },
                 ),
                 ListTile(
@@ -375,7 +372,7 @@ class SettingsPage extends StatelessWidget {
                     // TODO: give feedback
 
                   },
-                )
+                ),
               ],
             ),
             TitledColumn(title: Text(localizations.aboutWarnValuesScreen), children: [
app/pubspec.lock
@@ -595,14 +595,6 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "3.0.1"
-  restart_app:
-    dependency: "direct main"
-    description:
-      name: restart_app
-      sha256: b37daeb1c02fcab30e19d9e30b6fdd215bd53577efd927042eb77cf6f09daadb
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.2.1"
   shared_preferences:
     dependency: "direct main"
     description:
app/pubspec.yaml
@@ -34,7 +34,6 @@ dependencies:
   # can become one custom dependency
   file_picker: ^8.0.3  # MIT
   jsaver: ^1.2.0
-  restart_app: ^1.2.1
   fluttertoast: ^8.2.4
 
 dev_dependencies: