Commit e8d3a52
Changed files (4)
lib
lib/l10n/app_de.arb
@@ -37,6 +37,9 @@
"errNoData": "Keine Daten",
"errNoRangeForExport": "Sie müssen angeben, welche daten sie exportieren wollen.",
"errPleaseSelect": "Bitte auswählen",
+ "errNotCsvFormat": "Es können nur Dateien im csv Format importiert werden.",
+ "errNeedHeadline": "Es können nur Dateien mit einer Überschrift importiert werden.",
+
"btnCancel": "ABBRUCH",
"btnSave": "OK",
lib/l10n/app_en.arb
@@ -37,6 +37,9 @@
"errNoData": "no data",
"errNoRangeForExport": "You need to specify a range in which data is exported.",
"errPleaseSelect": "please select",
+ "errNotCsvFormat": "You can only import files in csv format.",
+ "errNeedHeadline": "You can only import files with a headline.",
+ "errCantReadFile": "The file contents can not be read",
"btnCancel": "CANCEL",
"btnSave": "SAVE",
lib/model/export_import.dart
@@ -29,7 +29,7 @@ class DataExporter {
csvHead += settings.csvFieldDelimiter;
}
}
- csvHead += '\n';
+ csvHead += '\r\n';
}
List<List<dynamic>> items = [];
@@ -64,6 +64,66 @@ class DataExporter {
}
return Uint8List(0);
}
+
+ List<BloodPressureRecord> parseCSVFile(Uint8List data) {
+ assert(settings.exportFormat == ExportFormat.csv);
+ assert(settings.exportCsvHeadline);
+
+ List<BloodPressureRecord> records = [];
+
+ String fileContents = utf8.decode(data.toList());
+ final converter = CsvToListConverter(fieldDelimiter: settings.csvFieldDelimiter, textDelimiter: settings.csvTextDelimiter);
+ final csvLines = converter.convert(fileContents);
+ if (csvLines.length <= 1) {
+ throw const FormatException('empty file');
+ }
+ final attributes = csvLines.removeAt(0);
+ var creationTimePos = -1;
+ var sysPos = -1;
+ var diaPos = -1;
+ var pulPos = -1;
+ var notePos = -1;
+ for (var i = 0; i<attributes.length; i++) {
+ switch (attributes[i]) {
+ case 'timestampUnixMs':
+ creationTimePos = i;
+ break;
+ case 'systolic':
+ sysPos = i;
+ break;
+ case 'diastolic':
+ diaPos = i;
+ break;
+ case 'pulse':
+ pulPos = i;
+ break;
+ case 'notes':
+ notePos = i;
+ break;
+ }
+ }
+ assert(creationTimePos >= 0);
+ assert(sysPos >= 0);
+ assert(diaPos >= 0);
+ assert(pulPos >= 0);
+ assert(notePos >= 0);
+
+ for (final line in csvLines) {
+ records.add(
+ BloodPressureRecord(
+ DateTime.fromMillisecondsSinceEpoch(line[creationTimePos]),
+ line[sysPos],
+ line[diaPos],
+ line[pulPos],
+ line[notePos]
+ )
+ );
+ }
+ // TODO: maybe use customized fields if no header is present?
+ // requires changes in screen class
+
+ return records;
+ }
}
class ExportFormat {
lib/screens/subsettings/export_import_screen.dart
@@ -6,6 +6,7 @@ import 'package:blood_pressure_app/components/settings_widgets.dart';
import 'package:blood_pressure_app/model/blood_pressure.dart';
import 'package:blood_pressure_app/model/export_import.dart';
import 'package:blood_pressure_app/model/settings_store.dart';
+import 'package:file_picker/file_picker.dart';
import 'package:file_saver/file_saver.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@@ -194,23 +195,36 @@ class ExportImportScreen extends StatelessWidget {
child: MaterialButton(
height: 60,
child: Text(AppLocalizations.of(context)!.import),
- onPressed: () {
- try {
- Provider.of<BloodPressureModel>(context, listen: false).import((res) {
- if (res) {
- ScaffoldMessenger.of(context).showSnackBar(SnackBar(
- content:
- Text(AppLocalizations.of(context)!.success(AppLocalizations.of(context)!.import))));
- } else {
- ScaffoldMessenger.of(context).showSnackBar(SnackBar(
- content: Text(AppLocalizations.of(context)!
- .error(AppLocalizations.of(context)!.errNoFileOpened))));
- }
- });
- } on Exception catch (e) {
- ScaffoldMessenger.of(context)
- .showSnackBar(SnackBar(content: Text(AppLocalizations.of(context)!.error(e.toString()))));
+ onPressed: () async {
+ final settings = Provider.of<Settings>(context, listen: false);
+ if (!(settings.exportFormat == ExportFormat.csv)) {
+ ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+ content: Text(AppLocalizations.of(context)!.errNotCsvFormat)));
+ }
+ if (!settings.exportCsvHeadline) {
+ ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+ content: Text(AppLocalizations.of(context)!.errNeedHeadline)));
+ }
+
+ // TODO: import from here
+
+
+ var result = await FilePicker.platform.pickFiles(
+ allowMultiple: false,
+ withData: true,
+ );
+ if (result == null) {
+ ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+ content: Text(AppLocalizations.of(context)!.errNoFileOpened)));
+ return;
+ }
+ var binaryContent = result.files.single.bytes;
+ if (binaryContent == null) {
+ ScaffoldMessenger.of(context).showSnackBar(SnackBar(
+ content: Text(AppLocalizations.of(context)!.errCantReadFile)));
+ return;
}
+ DataExporter(settings).parseCSVFile(binaryContent);
},
)
),