Commit 7bbf98d
Changed files (9)
android
app
lib
screens
subsettings
test
model
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: