Commit ac14227
Changed files (5)
lib
components
l10n
screens
subsettings
lib/components/export_item_order.dart
@@ -5,6 +5,7 @@ import 'package:badges/badges.dart' as badges;
import 'package:blood_pressure_app/components/consistent_future_builder.dart';
import 'package:blood_pressure_app/model/export_options.dart';
import 'package:blood_pressure_app/screens/subsettings/export_column_data.dart';
+import 'package:blood_pressure_app/screens/subsettings/export_fields_presets_list.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
@@ -33,68 +34,111 @@ class _ExportItemsCustomizerState extends State<ExportItemsCustomizer> {
return ConsistentFutureBuilder(
future: _future!,
onData: (BuildContext context, ExportConfigurationModel result) {
- return badges.Badge(
- badgeStyle: badges.BadgeStyle(
- badgeColor: Theme.of(context).colorScheme.background,
- padding: const EdgeInsets.all(10)
- ),
- position: badges.BadgePosition.bottomEnd(bottom: 3, end: 3),
- badgeContent: Container(
- decoration: BoxDecoration(
- border: Border.all(color: Theme.of(context).colorScheme.onBackground),
- shape: BoxShape.circle
- ),
- child: IconButton(
- tooltip: AppLocalizations.of(context)!.addExportformat,
- onPressed:() {
- Navigator.of(context).push(MaterialPageRoute(builder: (context) =>
- EditExportColumnPage(onValidSubmit: (value) {
- result.addOrUpdate(value);
- },)
- ));
- },
- icon: const Icon(Icons.add),
- ),
- ),
- child: Container(
- margin: const EdgeInsets.all(25),
- padding: const EdgeInsets.all(20),
- height: 420,
- decoration: BoxDecoration(
- border: Border.all(color: Theme.of(context).textTheme.labelLarge?.color ?? Colors.teal),
- borderRadius: const BorderRadius.all(Radius.circular(10)),
- ),
- clipBehavior: Clip.hardEdge,
- child: ReorderableListView(
- shrinkWrap: true,
- onReorder: _onReorderList,
- children: <Widget>[
- for (int i = 0; i < widget.shownItems.length; i += 1)
- ListTile(
- key: Key('l_${widget.shownItems[i].internalName}'),
- title: Text(widget.shownItems[i].columnTitle),
- trailing: _buildListItemTrailing( context, widget.shownItems[i]),
- contentPadding: EdgeInsets.zero
- ),
- _buildListSectionDivider(context),
- for (int i = 0; i < widget.hiddenItems.length; i += 1)
- ListTile(
- key: Key('ul_${widget.hiddenItems[i].internalName}'),
- title: Opacity(
- opacity: 0.7,
- child: Text(widget.hiddenItems[i].columnTitle),
- ),
- trailing: _buildListItemTrailing(context, widget.hiddenItems[i]),
- contentPadding: EdgeInsets.zero
- ),
- ],
- ),
- ),
+ return _buildAddItemBadge(context, result,
+ child: _buildManagePresetsBadge(context, result,
+ child:_buildList(context))
);
},
);
}
+ Container _buildList(BuildContext context) {
+ return Container(
+ margin: const EdgeInsets.all(25),
+ padding: const EdgeInsets.all(20),
+ height: 420,
+ decoration: BoxDecoration(
+ border: Border.all(color: Theme.of(context).textTheme.labelLarge?.color ?? Colors.teal),
+ borderRadius: const BorderRadius.all(Radius.circular(10)),
+ ),
+ clipBehavior: Clip.hardEdge,
+ child: ReorderableListView(
+ shrinkWrap: true,
+ onReorder: _onReorderList,
+ children: <Widget>[
+ for (int i = 0; i < widget.shownItems.length; i += 1)
+ ListTile(
+ key: Key('l_${widget.shownItems[i].internalName}'),
+ title: Text(widget.shownItems[i].columnTitle),
+ trailing: _buildListItemTrailing( context, widget.shownItems[i]),
+ contentPadding: EdgeInsets.zero
+ ),
+ _buildListSectionDivider(context),
+ for (int i = 0; i < widget.hiddenItems.length; i += 1)
+ ListTile(
+ key: Key('ul_${widget.hiddenItems[i].internalName}'),
+ title: Opacity(
+ opacity: 0.7,
+ child: Text(widget.hiddenItems[i].columnTitle),
+ ),
+ trailing: _buildListItemTrailing(context, widget.hiddenItems[i]),
+ contentPadding: EdgeInsets.zero
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _buildAddItemBadge(BuildContext context, ExportConfigurationModel result, {required Widget child}) {
+ return badges.Badge(
+ badgeStyle: badges.BadgeStyle(
+ badgeColor: Theme.of(context).colorScheme.background,
+ padding: const EdgeInsets.all(10)
+ ),
+ position: badges.BadgePosition.bottomEnd(bottom: 3, end: 3),
+ badgeContent: Container(
+ decoration: BoxDecoration(
+ border: Border.all(color: Theme.of(context).colorScheme.onBackground),
+ shape: BoxShape.circle
+ ),
+ child: IconButton(
+ tooltip: AppLocalizations.of(context)!.addExportformat,
+ onPressed:() {
+ Navigator.of(context).push(MaterialPageRoute(builder: (context) =>
+ EditExportColumnPage(onValidSubmit: (value) {
+ result.addOrUpdate(value);
+ },)
+ ));
+ },
+ icon: const Icon(Icons.add),
+ ),
+ ),
+ child: child,
+ );
+ }
+
+ Widget _buildManagePresetsBadge(BuildContext context, ExportConfigurationModel result, {required Widget child}) {
+ final localizations = AppLocalizations.of(context)!;
+ return badges.Badge(
+ position: badges.BadgePosition.topEnd(top: 3, end: 3),
+ badgeStyle: badges.BadgeStyle(
+ badgeColor: Theme.of(context).colorScheme.background,
+ padding: const EdgeInsets.all(5)
+ ),
+ badgeContent: PopupMenuButton<int>(
+ icon: const Icon(Icons.collections_bookmark),
+ itemBuilder: (BuildContext context) {
+ return [
+ PopupMenuItem<int>(value: 0, child: Text(localizations.default_)),
+ const PopupMenuItem<int>(value: 1, child: Text('"My Heart" export'))
+ ];
+ },
+ onSelected: (value) {
+ switch (value) {
+ case 0:
+ result.settings.exportItems = ['timestampUnixMs', 'systolic', 'diastolic', 'pulse', 'notes'];
+ return;
+ case 1:
+ result.settings.exportItems = ['DATUM', 'SYSTOLE', 'DIASTOLE', 'PULS', 'Beschreibung', 'Tags', 'Gewicht', 'Sauerstoffsättigung'];
+ return;
+ }
+ assert(false);
+ },
+ ),
+ child: child,
+ );
+ }
+
Widget _buildListItemTrailing(BuildContext context, ExportColumn data) {
return Row(
mainAxisSize: MainAxisSize.min,
lib/l10n/app_en.arb
@@ -381,5 +381,9 @@
"delete": "Delete",
"@delete": {},
"exportFieldFormatDocumentation": "'## Variables\nThe export field format support inserting values for the following placeholders:\n- `$TIMESTAMP:` Represents the time since the Unix epoch in milliseconds.\n- `$SYS:` Provides a value if available; otherwise, it defaults to -1.\n- `$DIA:` Provides a value if available; otherwise, it defaults to -1.\n- `$PUL:` Provides a value if available; otherwise, it defaults to -1.\n- `$NOTE:` Provides a value if available; otherwise, it defaults to -1.\n\nIf any of the placeholders mentioned above are not present in the blood pressure record, they will be replaced with -1.\n\n## Math\nYou can use basic mathematics inside double brackets (\"`{{}}`\").\n\nThe following mathematical operations are supported:\n- Operations: +, -, *, /, %, ^\n- One-parameter functions: abs, acos, asin, atan, ceil, cos, cosh, cot, coth, csc, csch, exp, floor, ln, log, round sec, sech, sin, sinh, sqrt, tan, tanh \n- Two-parameter functions: log, nrt, pow\n- Constants: e, pi, ln2, ln10, log2e, log10e, sqrt1_2, sqrt2\nFor the full math interpreter specification, you can refer to the [function_tree](https://pub.dev/documentation/function_tree/latest#interpreter) specification\n\n## Time\nTo format a timestamp, use the following syntax: `$FORMAT{<timestamp>,<formatString>}`. The `<formatString>` supports the same format as described on the ICU/Skeleton string [documentation page](screen://TimeFormattingHelp).\n\n## Processing order\n1. variable replacement\n2. Math\n3. Date format'",
- "@exportFieldFormatDocumentation": {}
+ "@exportFieldFormatDocumentation": {},
+ "presets": "Presets",
+ "@presets": {},
+ "default_": "Default",
+ "@default_": {}
}
lib/model/export_import.dart
@@ -68,7 +68,7 @@ class ExportFileCreator {
if (settings.exportCustomEntries) {
exportItems = exportColumnsConfig.getActiveExportColumns();
} else {
- exportItems = exportColumnsConfig.getDefaultFormates();
+ exportItems = exportColumnsConfig.getDefaultFormates().where((e) => ['timestampUnixMs','systolic','diastolic','pulse','notes'].contains(e.internalName)).toList();
}
var csvHead = '';
lib/model/export_options.dart
@@ -56,14 +56,23 @@ class ExportConfigurationModel {
return activeFields;
}
- List<ExportColumn> getDefaultFormates() => [
+ List<ExportColumn> getDefaultFormates() => [ // TODO: hidde fields unless user wants to explicitly see them
ExportColumn(internalName: 'timestampUnixMs', columnTitle: localizations.unixTimestamp, formatPattern: r'$TIMESTAMP', editable: false),
ExportColumn(internalName: 'formattedTimestamp', columnTitle: localizations.time, formatPattern: '\$FORMAT{\$TIMESTAMP,${settings.dateFormatString}}', editable: false),
ExportColumn(internalName: 'systolic', columnTitle: localizations.sysLong, formatPattern: r'$SYS', editable: false),
ExportColumn(internalName: 'diastolic', columnTitle: localizations.diaLong, formatPattern: r'$DIA', editable: false),
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: 'pulsePressure', columnTitle: localizations.pulsePressure, formatPattern: r'{{$SYS-$DIA}}', editable: false),
+
+ ExportColumn(internalName: 'DATUM', columnTitle: '"My Heart" export time', formatPattern: r'$FORMAT{$TIMESTAMP,yyyy-mm-dd HH:mm:ss}', editable: false),
+ ExportColumn(internalName: 'SYSTOLE', columnTitle: '"My Heart" export sys', formatPattern: r'$SYS', editable: false),
+ ExportColumn(internalName: 'DIASTOLE', columnTitle: '"My Heart" export dia', formatPattern: r'$DIA', editable: false),
+ ExportColumn(internalName: 'PULS', columnTitle: '"My Heart" export pul', formatPattern: r'$PUL', editable: false),
+ ExportColumn(internalName: 'Beschreibung', columnTitle: '"My Heart" export description', formatPattern: r'null', editable: false),
+ ExportColumn(internalName: 'Tags', columnTitle: '"My Heart" export tags', formatPattern: r'', editable: false),
+ ExportColumn(internalName: 'Gewicht', columnTitle: '"My Heart" export weight', formatPattern: r'0.0', editable: false),
+ ExportColumn(internalName: 'Sauerstoffsättigung', columnTitle: '"My Heart" export oxygen', formatPattern: r'0', editable: false),
];
void addOrUpdate(ExportColumn format) {
lib/screens/subsettings/export_import_screen.dart
@@ -214,7 +214,7 @@ class _ExportWarnBannerState extends State<ExportWarnBanner> {
return Consumer<Settings>(builder: (context, settings, child) {
if (_showWarnBanner && ![ExportFormat.csv, ExportFormat.db].contains(settings.exportFormat) ||
settings.exportCsvHeadline == false ||
- settings.exportCustomEntries && !(['timestampUnixMs','isoUTCTime'].any((i) => settings.exportItems.contains(i))) ||
+ settings.exportCustomEntries && !(['timestampUnixMs'].any((i) => settings.exportItems.contains(i))) ||
![',', '|'].contains(settings.csvFieldDelimiter) ||
!['"', '\''].contains(settings.csvTextDelimiter)
) {