Commit 08d29db
Changed files (3)
lib
screens
subsettings
lib/model/export_import.dart
@@ -51,7 +51,7 @@ class ExportFileCreator {
try {
return parseCSVFile(data);
} catch (e) {
- return null;
+ return Future.error(e);
}
case ExportFormat.pdf:
return null;
@@ -84,6 +84,7 @@ class ExportFileCreator {
for (var lineIndex = 0; lineIndex < csvLines.length; lineIndex++) {
// get values from columns
int? timestamp, sys, dia, pul;
+ Color? color;
String? notes;
for (var attributeIndex = 0; attributeIndex < attributes.length; attributeIndex++) {
if (timestamp != null && sys != null && dia !=null && pul != null) continue; // optimization
@@ -119,6 +120,8 @@ class ExportFileCreator {
assert(parsedRecordDataType.$2 is int?);
timestamp ??= parsedRecordDataType.$2 as int?;
break;
+ case RowDataFieldType.color:
+ color ??= parsedRecordDataType.$2 as Color?;
}
}
}
@@ -127,7 +130,8 @@ class ExportFileCreator {
if (timestamp == null) {
throw ArgumentError('File didn\'t save timestamps');
}
- records.add(BloodPressureRecord(DateTime.fromMillisecondsSinceEpoch(timestamp), sys, dia, pul, notes ?? ''));
+ records.add(BloodPressureRecord(DateTime.fromMillisecondsSinceEpoch(timestamp), sys, dia, pul, notes ?? '',
+ needlePin: (color == null) ? null : MeasurementNeedlePin(color)));
}
return records;
}
@@ -307,8 +311,17 @@ class Exporter {
var path = result.files.single.path;
assert(path != null); // null state directly linked to binary content
- var fileContents = await ExportFileCreator(settings, localizations, theme, exportColumnsConfig).parseFile(path! ,binaryContent);
- if (fileContents == null) {
+ final fileContentsFuture = ExportFileCreator(settings, localizations, theme, exportColumnsConfig).parseFile(path! ,binaryContent);
+ Object? fileContentsError;
+ fileContentsFuture.onError((error, stackTrace) {
+ fileContentsError = error;
+ return null;
+ });
+ var fileContents = await fileContentsFuture;
+ if (fileContentsError != null) {
+ messenger.showSnackBar(SnackBar(content: Text(localizations.error(fileContentsError.toString()))));
+ return;
+ } else if (fileContents == null) {
messenger.showSnackBar(SnackBar(content: Text(localizations.errNotImportable)));
return;
}
lib/model/export_options.dart
@@ -4,6 +4,7 @@ import 'package:blood_pressure_app/main.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:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:function_tree/function_tree.dart';
import 'package:intl/intl.dart';
@@ -27,7 +28,7 @@ class ExportConfigurationModel {
/// Format: (title, List<internalNameOfExportFormat>)
List<(String, List<String>)> get exportConfigurations => [
// Not fully localized, as potential user added configurations can't be localized as well
- (localizations.default_, ['timestampUnixMs', 'systolic', 'diastolic', 'pulse', 'notes']),
+ (localizations.default_, ['timestampUnixMs', 'systolic', 'diastolic', 'pulse', 'notes', 'color']),
('"My Heart" export', ['DATUM', 'SYSTOLE', 'DIASTOLE', 'PULS', 'Beschreibung', 'Tags', 'Gewicht', 'Sauerstoffsättigung']),
];
@@ -86,6 +87,7 @@ class ExportConfigurationModel {
ExportColumn(internalName: 'pulse', columnTitle: localizations.pulLong, formatPattern: r'$PUL', editable: false),
ExportColumn(internalName: 'notes', columnTitle: localizations.notes, formatPattern: r'$NOTE', editable: false),
ExportColumn(internalName: 'pulsePressure', columnTitle: localizations.pulsePressure, formatPattern: r'{{$SYS-$DIA}}', editable: false),
+ ExportColumn(internalName: 'color', columnTitle: localizations.color, formatPattern: r'$COLOR', editable: false),
ExportColumn(internalName: 'DATUM', columnTitle: '"My Heart" export time', formatPattern: r'$FORMAT{$TIMESTAMP,yyyy-MM-dd HH:mm:ss}', editable: false, hidden: true),
ExportColumn(internalName: 'SYSTOLE', columnTitle: '"My Heart" export sys', formatPattern: r'$SYS', editable: false, hidden: true),
@@ -201,6 +203,7 @@ class ExportColumn {
fieldContents = fieldContents.replaceAll(r'$DIA', record.diastolic.toString());
fieldContents = fieldContents.replaceAll(r'$PUL', record.pulse.toString());
fieldContents = fieldContents.replaceAll(r'$NOTE', record.notes.toString());
+ fieldContents = fieldContents.replaceAll(r'$COLOR', record.needlePin?.color.value.toString() ?? '');
// math
fieldContents = fieldContents.replaceAllMapped(RegExp(r'\{\{([^}]*)}}'), (m) {
@@ -227,6 +230,12 @@ class ExportColumn {
if (!isReversible || formattedRecord == 'null') return [];
if (formatPattern == r'$NOTE') return [(RowDataFieldType.notes, formattedRecord)];
+ if (formatPattern == r'$COLOR') {
+ final value = int.tryParse(formattedRecord);
+ print(value);
+ print(formattedRecord);
+ return value == null ? [] : [(RowDataFieldType.color, Color(value))];
+ }
// records are parse by replacing the values with capture groups
final types = RegExp(r'\$(TIMESTAMP|SYS|DIA|PUL)').allMatches(formatPattern).map((e) => e.group(0)).toList();
@@ -262,13 +271,14 @@ class ExportColumn {
/// Checks if the pattern can be used to parse records. This is the case when the pattern contains variables without
/// containing curly brackets or commas.
bool get isReversible {
- return (formatPattern == r'$TIMESTAMP') ||
+ return (formatPattern == r'$TIMESTAMP') || (formatPattern == r'$COLOR') ||
formatPattern.contains(RegExp(r'\$(SYS|DIA|PUL|NOTE)')) && !formatPattern.contains(RegExp(r'[{},]'));
}
RowDataFieldType? get parsableFormat {
if (formatPattern.contains(RegExp(r'[{},]'))) return null;
if (formatPattern == r'$TIMESTAMP') return RowDataFieldType.timestamp;
+ if (formatPattern == r'$COLOR') return RowDataFieldType.color;
if (formatPattern.contains(RegExp(r'\$(SYS)'))) return RowDataFieldType.sys;
if (formatPattern.contains(RegExp(r'\$(DIA)'))) return RowDataFieldType.dia;
if (formatPattern.contains(RegExp(r'\$(PUL)'))) return RowDataFieldType.pul;
@@ -283,7 +293,7 @@ class ExportColumn {
}
enum RowDataFieldType {
- timestamp, sys, dia, pul, notes;
+ timestamp, sys, dia, pul, notes, color;
@override
String toString() {
@@ -298,6 +308,8 @@ enum RowDataFieldType {
return gLocalizations.pulLong;
case 4:
return gLocalizations.notes;
+ case 5:
+ return gLocalizations.color;
default:
return "unknown";
};
lib/screens/subsettings/export_import_screen.dart
@@ -303,8 +303,7 @@ class ExportImportButtons extends StatelessWidget {
messenger,
localizations,
theme,
- await ExportConfigurationModel.get(
- settings, localizations))
+ await ExportConfigurationModel.get(settings, localizations))
.import(),
)),
],
@@ -347,7 +346,8 @@ class _ExportWarnBannerState extends State<ExportWarnBanner> {
RowDataFieldType.sys,
RowDataFieldType.dia,
RowDataFieldType.pul,
- RowDataFieldType.notes
+ RowDataFieldType.notes,
+ RowDataFieldType.color
};
missingAttributes.removeWhere((e) => exportFormats.contains(e));
if (_showWarnBanner &&