Commit 7bbf98d

derdilla <derdilla06@gmail.com>
2023-06-24 10:08:07
add default export dir
1 parent 7d48442
android/app/build.gradle
@@ -52,7 +52,7 @@ android {
         applicationId "com.derdilla.bloodPressureApp"
         // You can update the following values to match your application needs.
         // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
-        minSdkVersion 19
+        minSdkVersion 21
         targetSdkVersion flutter.targetSdkVersion
         versionCode 14
         versionName "1.3.2"
lib/l10n/app_de.arb
@@ -85,6 +85,7 @@
   "data": "Daten",
 
   "exportImport": "Exportieren / Importieren",
+  "exportDir": "Export ordbner",
   "exportLimitDataRange": "Datenbereich einschränken",
   "exportInterval": "Datenbereich",
   "exportFormat": "Exportformat",
lib/l10n/app_en.arb
@@ -84,6 +84,7 @@
   "data": "Data",
 
   "exportImport": "Export / Import",
+  "exportDir": "Export directory",
   "exportLimitDataRange": "Limit data range",
   "exportInterval": "Data range",
   "exportFormat": "Export format",
lib/model/ram_only_implementations.dart
@@ -113,6 +113,7 @@ class RamSettings extends ChangeNotifier implements Settings {
   List<String> _exportItems = ['timestampUnixMs', 'systolic', 'diastolic', 'pulse', 'notes'];
   bool _exportLimitDataRange = false;
   MimeType _exportMimeType = MimeType.csv;
+  String _defaultExportDir = '';
 
   RamSettings() {
     _accentColor = createMaterialColor(0xFF009688);
@@ -421,6 +422,15 @@ class RamSettings extends ChangeNotifier implements Settings {
     notifyListeners();
   }
 
+  @override
+  String get defaultExportDir => _defaultExportDir;
+
+  @override
+  set defaultExportDir(String value) {
+    _defaultExportDir = value;
+    notifyListeners();
+  }
+
   @override
   void changeStepSize(int value) {
     graphStepSize = value;
lib/model/settings_store.dart
@@ -411,6 +411,14 @@ class Settings extends ChangeNotifier {
     _prefs.setBool('exportCsvHeadline', value);
     notifyListeners();
   }
+
+  String get defaultExportDir {
+    return _prefs.getString('defaultExportDir') ?? '';
+  }
+  set defaultExportDir (String value) {
+    _prefs.setString('defaultExportDir', value);
+    notifyListeners();
+  }
 }
 
 class TimeStep {
lib/screens/subsettings/export_import_screen.dart
@@ -11,6 +11,7 @@ import 'package:file_saver/file_saver.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 import 'package:intl/intl.dart';
+import 'package:jsaver/jSaver.dart';
 import 'package:provider/provider.dart';
 import 'package:share_plus/share_plus.dart';
 
@@ -31,6 +32,14 @@ class ExportImportScreen extends StatelessWidget {
             child: Column(
               children: [
                 const ExportWarnBanner(),
+                SettingsTile(
+                  title: Text(AppLocalizations.of(context)!.exportDir),
+                  description: Text(settings.defaultExportDir),
+                  onPressed: (context) async {
+                    final appDir = await JSaver.instance.setDefaultSavingDirectory();
+                    settings.defaultExportDir = appDir.value;
+                  }
+                ),
                 DropDownSettingsTile<ExportFormat>(
                   key: const Key('exportFormat'),
                   title: Text(AppLocalizations.of(context)!.exportFormat),
@@ -298,13 +307,13 @@ class ExportImportButtons extends StatelessWidget {
                     String ext;
                     switch(settings.exportFormat) {
                       case ExportFormat.csv:
-                        ext = '.csv';
+                        ext = 'CSV'; // lower case 'csv' gets automatically converted to 'csv.xls' for some reason
                         break;
                       case ExportFormat.pdf:
-                        ext = '.pdf';
+                        ext = 'pdf';
                         break;
                       case ExportFormat.db:
-                        ext = '.db';
+                        ext = 'db';
                         break;
                     }
                     String path = await FileSaver.instance.saveFile(name: filename, ext: ext, bytes: fileContents);
@@ -313,12 +322,19 @@ class ExportImportButtons extends StatelessWidget {
                       ScaffoldMessenger.of(context)
                           .showSnackBar(SnackBar(content: Text(AppLocalizations.of(context)!.success(path))));
                     } else if (Platform.isAndroid || Platform.isIOS) {
-                      Share.shareXFiles([
-                        XFile(
-                            path,
-                            mimeType: MimeType.csv.type
-                        )
-                      ]);
+                      if (settings.defaultExportDir.isNotEmpty) {
+                        JSaver.instance.save(
+                            fromPath: path,
+                            androidPathOptions: AndroidPathOptions(toDefaultDirectory: true)
+                        );
+                      } else {
+                        Share.shareXFiles([
+                          XFile(
+                              path,
+                              mimeType: MimeType.csv.type
+                          )
+                        ]);
+                      }
                     } else {
                       ScaffoldMessenger.of(context)
                           .showSnackBar(const SnackBar(content: Text('UNSUPPORTED PLATFORM')));
test/model/settings_test.dart
@@ -49,6 +49,7 @@ void main() {
       expect(s.exportDataRange.start.millisecondsSinceEpoch, 0);
       expect(s.exportLimitDataRange, false);
       expect(s.exportMimeType, MimeType.csv);
+      expect(s.defaultExportDir.isEmpty, true);
 
       s.overrideWarnValues = true;
       expect(s.sysWarn, 120);
@@ -96,6 +97,7 @@ void main() {
       s.exportCsvHeadline = false;
       s.exportLimitDataRange = true;
       s.exportMimeType = MimeType.pdf;
+      s.defaultExportDir = '/storage/emulated/0/Android/data/com.derdilla.bloodPressureApp/files/file.csv';
 
       expect(s.displayDataStart, DateTime.fromMillisecondsSinceEpoch(10000));
       expect(s.displayDataEnd, DateTime.fromMillisecondsSinceEpoch(200000));
@@ -123,6 +125,7 @@ void main() {
       expect(s.exportCsvHeadline, false);
       expect(s.exportLimitDataRange, true);
       expect(s.exportMimeType, MimeType.pdf);
+      expect(s.defaultExportDir, '/storage/emulated/0/Android/data/com.derdilla.bloodPressureApp/files/file.csv');
     });
 
     test('setting fields should notify listeners and change values', () async {
@@ -162,8 +165,9 @@ void main() {
       s.exportDataRange = DateTimeRange(start: DateTime.fromMillisecondsSinceEpoch(20), end: DateTime.now());
       s.exportLimitDataRange = true;
       s.exportMimeType = MimeType.pdf;
+      s.defaultExportDir = '/storage/emulated/0/Android/data/com.derdilla.bloodPressureApp/files/file.csv';
 
-      expect(i, 29);
+      expect(i, 30);
     });
   });
 
@@ -206,6 +210,7 @@ void main() {
       expect(s.exportDataRange.start.millisecondsSinceEpoch, 0);
       expect(s.exportLimitDataRange, false);
       expect(s.exportMimeType, MimeType.csv);
+      expect(s.defaultExportDir.isEmpty, true);
 
       s.overrideWarnValues = true;
       expect(s.sysWarn, 120);
@@ -253,6 +258,8 @@ void main() {
       s.exportCsvHeadline = false;
       s.exportLimitDataRange = true;
       s.exportMimeType = MimeType.pdf;
+      s.defaultExportDir = '/storage/emulated/0/Android/data/com.derdilla.bloodPressureApp/files/file.csv';
+
 
       expect(s.displayDataStart, DateTime.fromMillisecondsSinceEpoch(10000));
       expect(s.displayDataEnd, DateTime.fromMillisecondsSinceEpoch(200000));
@@ -280,6 +287,7 @@ void main() {
       expect(s.exportCsvHeadline, false);
       expect(s.exportLimitDataRange, true);
       expect(s.exportMimeType, MimeType.pdf);
+      expect(s.defaultExportDir, '/storage/emulated/0/Android/data/com.derdilla.bloodPressureApp/files/file.csv');
     });
 
     test('setting fields should notify listeners and change values', () async {
@@ -319,8 +327,9 @@ void main() {
       s.exportDataRange = DateTimeRange(start: DateTime.fromMillisecondsSinceEpoch(20), end: DateTime.now());
       s.exportLimitDataRange = true;
       s.exportMimeType = MimeType.pdf;
+      s.defaultExportDir = '/storage/emulated/0/Android/data/com.derdilla.bloodPressureApp/files/file.csv';
 
-      expect(i, 29);
+      expect(i, 30);
     });
   });
 }
pubspec.lock
@@ -357,6 +357,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "0.6.7"
+  jsaver:
+    dependency: "direct main"
+    description:
+      name: jsaver
+      sha256: "7f18f134d3271e5b9da0ccbf0bd6766cb4e6a0221cc26f4d917b1da023331600"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.2.0"
   json_object_mapper:
     dependency: transitive
     description:
pubspec.yaml
@@ -47,6 +47,7 @@ dependencies:
   shared_preferences: ^2.1.1  # BSD-3-Clause
   mockito: ^5.4.1
   pdf: ^3.10.4
+  jsaver: ^1.2.0
 
 dev_dependencies:
   flutter_test: