Commit 79767a2
Changed files (10)
lib/l10n/app_de.arb
@@ -39,7 +39,7 @@
},
"errNoFileOpened": "Keine Datei geöffnet",
"@errNoFileOpened": {},
- "errNotStarted": "Nicht begonnen'",
+ "errNotStarted": "Nicht begonnen",
"@errNotStarted": {},
"errNoValue": "Bitte Wert eingeben",
"@errNoValue": {},
lib/l10n/app_en.arb
@@ -29,7 +29,7 @@
"@errDiaGtSys": {},
"errUnknown": "Unknown error",
"@errUnknown": {},
- "errCantOpenURL": "Can't open URL: {url}",
+ "errCantOpenURL": "Can''t open URL: {url}",
"@errCantOpenURL": {
"placeholders": {
"url": {
@@ -53,9 +53,9 @@
"@errWrongImportFormat": {},
"errNeedHeadline": "You can only import files with a headline.",
"@errNeedHeadline": {},
- "errCantReadFile": "The file's contents can not be read",
+ "errCantReadFile": "The file''s contents can not be read",
"@errCantReadFile": {},
- "errNotImportable": "This file can't be imported",
+ "errNotImportable": "This file can''t be imported",
"@errNotImportable": {},
"btnCancel": "CANCEL",
"@btnCancel": {},
@@ -233,7 +233,7 @@
}
}
},
- "exportWarnConfigNotImportable": "Hey! Just a friendly heads up: the current export configuration won't be importable. To fix it, make sure you set the export type as CSV, enable the headline, and include one of the time formats available.",
+ "exportWarnConfigNotImportable": "Hey! Just a friendly heads up: the current export configuration won''t be importable. To fix it, make sure you set the export type as CSV, enable the headline, and include one of the time formats available.",
"@exportWarnConfigNotImportable": {},
"exportWarnNotEveryFieldExported": "Beware that you are not exporting all fields: {fields} {count, plural, one{is} other{are}} missing.",
"@exportWarnNotEveryFieldExported": {
@@ -286,11 +286,11 @@
"@warnAboutTxt2": {},
"warnAboutTxt3": "Feel free to change the values to suit your needs and follow the recommendations of your doctor.",
"@warnAboutTxt3": {},
- "enterTimeFormatTxt1": "A formatter string is a blend of predefined ICU/Skeleton strings and any additional text you'd like to include.",
+ "enterTimeFormatTxt1": "A formatter string is a blend of predefined ICU/Skeleton strings and any additional text you''d like to include.",
"@enterTimeFormatTxt1": {},
- "enterTimeFormatTxt2": "If you're curious about the complete list of valid formats, you can find them right here.",
+ "enterTimeFormatTxt2": "If you''re curious about the complete list of valid formats, you can find them right here.",
"@enterTimeFormatTxt2": {},
- "enterTimeFormatTxt3": "Just a friendly reminder, using longer or shorter format Strings won't magically alter the width of the table columns, which might lead to some awkward line breaks and text not showing.",
+ "enterTimeFormatTxt3": "Just a friendly reminder, using longer or shorter format Strings won''t magically alter the width of the table columns, which might lead to some awkward line breaks and text not showing.",
"@enterTimeFormatTxt3": {},
"enterTimeFormatTxt4": "default: \"yy-MM-dd HH:mm\"",
"@enterTimeFormatTxt4": {},
@@ -373,11 +373,13 @@
"@pulsePressure": {},
"unixTimestamp" : "Unix timestamp",
"@unixTimestamp": {},
- "errCantEditThis": "You can't edit this. Feel free to look at the values for creating a new entry.",
+ "errCantEditThis": "You can''t edit this. Feel free to look at the values for creating a new entry.",
"addExportformat": "Add exportformat",
"@addExportformat": {},
"edit": "Edit",
"@edit": {},
"delete": "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": {}
}
lib/l10n/app_fr.arb
@@ -25,7 +25,7 @@
"@btnConfirm": {},
"sysLong": "Systolique",
"@sysLong": {},
- "allowManualTimeInput": "Permettre la saisie manuelle de l'heure",
+ "allowManualTimeInput": "Permettre la saisie manuelle de l''heure",
"@allowManualTimeInput": {},
"btnUndo": "ANNULER",
"@btnUndo": {},
@@ -33,17 +33,17 @@
"@btnNext": {},
"pulLong": "Pouls",
"@pulLong": {},
- "enterTimeFormatScreen": "Format de l'heure",
+ "enterTimeFormatScreen": "Format de l''heure",
"@enterTimeFormatScreen": {},
"theme": "Thème",
"@theme": {},
"light": "Clair",
"@light": {},
- "iconSize": "Taille de l'icône",
+ "iconSize": "Taille de l''icône",
"@iconSize": {},
"graphLineThickness": "Épaisseur de la ligne",
"@graphLineThickness": {},
- "animationSpeed": "Durée de l'animation",
+ "animationSpeed": "Durée de l''animation",
"@animationSpeed": {},
"behavior": "Comportement",
"@behavior": {},
@@ -63,7 +63,7 @@
}
}
},
- "exportFormat": "Format d'exportation",
+ "exportFormat": "Format d''exportation",
"@exportFormat": {},
"export": "EXPORTER",
"@export": {},
@@ -71,7 +71,7 @@
"@exportCustomEntries": {},
"textDelimiter": "Délimiteur de texte",
"@textDelimiter": {},
- "enterTimeFormatTxt1": "Une chaine de formatage est un mélange de chaines ICU/Skeleton et de n'importe quel texte supplémentaire que vous souhaitez inclure.",
+ "enterTimeFormatTxt1": "Une chaine de formatage est un mélange de chaines ICU/Skeleton et de n''importe quel texte supplémentaire que vous souhaitez inclure.",
"@enterTimeFormatTxt1": {},
"enterTimeFormatTxt2": "Si vous souhaitez en savoir plus sur la liste complète des formats valides, vous pouvez trouver ces derniers juste ici.",
"@enterTimeFormatTxt2": {},
@@ -103,7 +103,7 @@
"@errDiaGtSys": {},
"errUnknown": "Erreur inconnue",
"@errUnknown": {},
- "errCantOpenURL": "Impossible d'ouvrir l'adresse {url}",
+ "errCantOpenURL": "Impossible d''ouvrir l''adresse {url}",
"@errCantOpenURL": {
"placeholders": {
"url": {
@@ -121,13 +121,13 @@
"@errNotEnoughDataToGraph": {},
"errNoData": "pas de données",
"@errNoData": {},
- "errNeedHeadline": "Vous ne pouvez importer que des fichiers avec une ligne d'entête.",
+ "errNeedHeadline": "Vous ne pouvez importer que des fichiers avec une ligne d''entête.",
"@errNeedHeadline": {},
"errCantReadFile": "Le contenu du fichier ne peut pas être lu",
"@errCantReadFile": {},
"errNotImportable": "Ce fichier ne peut pas être importé",
"@errNotImportable": {},
- "graphTitlesCount": "Compteur d'étiquettes de graphique",
+ "graphTitlesCount": "Compteur d''étiquettes de graphique",
"@graphTitlesCount": {},
"accentColor": "Couleur du thème",
"@accentColor": {},
@@ -141,11 +141,11 @@
"@validateInputs": {},
"age": "Âge",
"@age": {},
- "determineWarnValues": "Déterminer les valeurs d'alerte",
+ "determineWarnValues": "Déterminer les valeurs d''alerte",
"@determineWarnValues": {},
"aboutWarnValuesScreen": "À propos",
"@aboutWarnValuesScreen": {},
- "aboutWarnValuesScreenDesc": "Plus d'informations sur les valeurs d'alerte",
+ "aboutWarnValuesScreenDesc": "Plus d''informations sur les valeurs d''alerte",
"@aboutWarnValuesScreenDesc": {},
"sysWarn": "Alerte sur la systole",
"@sysWarn": {},
@@ -179,7 +179,7 @@
},
"sharedPrefsDump": "Contenu des préférences partagées :",
"@sharedPrefsDump": {},
- "exportDir": "Répertoire d'export",
+ "exportDir": "Répertoire d''export",
"@exportDir": {},
"exportAfterEveryInput": "Exporter après chaque saisie",
"@exportAfterEveryInput": {},
@@ -195,7 +195,7 @@
"@exportMimeType": {},
"exportMimeTypeDesc": "Signaler le type aux autres applications",
"@exportMimeTypeDesc": {},
- "exportCsvHeadline": "Ligne d'entête",
+ "exportCsvHeadline": "Ligne d''entête",
"@exportCsvHeadline": {},
"exportCsvHeadlineDesc": "Aide pour distinguer les types",
"@exportCsvHeadlineDesc": {},
@@ -237,9 +237,9 @@
},
"statistics": "Statistiques",
"@statistics": {},
- "exportWarnConfigNotImportable": "Coucou ! Ceci est juste un avertissement amical : les options d'export choisies ne seront pas importables. Pour corriger cela, choisissez un export en CSV, activez la ligne d'entête et sélectionnez un des formats d'heure disponibles.",
+ "exportWarnConfigNotImportable": "Coucou ! Ceci est juste un avertissement amical : les options d''export choisies ne seront pas importables. Pour corriger cela, choisissez un export en CSV, activez la ligne d''entête et sélectionnez un des formats d''heure disponibles.",
"@exportWarnConfigNotImportable": {},
- "exportWarnNotEveryFieldExported": "Attention, vous n'exportez pas tous les champs : {fields} {count, plural, one{est manquant} other{sont manquants}}.",
+ "exportWarnNotEveryFieldExported": "Attention, vous n''exportez pas tous les champs : {fields} {count, plural, one{est manquant} other{sont manquants}}.",
"@exportWarnNotEveryFieldExported": {
"placeholders": {
"count": {
@@ -280,17 +280,17 @@
}
}
},
- "warnValues": "Valeurs d'alerte",
+ "warnValues": "Valeurs d''alerte",
"@warnValues": {},
- "warnAboutTxt1": "Les valeurs d'alerte ne sont que des suggestions et n'ont pas valeur d'avis médical.",
+ "warnAboutTxt1": "Les valeurs d''alerte ne sont que des suggestions et n''ont pas valeur d''avis médical.",
"@warnAboutTxt1": {},
- "warnAboutTxt2": "Les valeurs par défaut dépendant de l'âge proviennent de cette source.",
+ "warnAboutTxt2": "Les valeurs par défaut dépendant de l''âge proviennent de cette source.",
"@warnAboutTxt2": {},
- "warnAboutTxt3": "N'hésitez pas à modifier les valeurs pour qu'elles vous conviennent et suivent les recommandations de votre médecin.",
+ "warnAboutTxt3": "N''hésitez pas à modifier les valeurs pour qu''elles vous conviennent et suivent les recommandations de votre médecin.",
"@warnAboutTxt3": {},
"enterTimeFormatTxt4": "valeur par défaut : \"yy-MM-dd HH:mm\"",
"@enterTimeFormatTxt4": {},
- "enterTimeFormatString": "format d'heure",
+ "enterTimeFormatString": "format d''heure",
"@enterTimeFormatString": {},
"dateFormatting": "Formatage de date",
"@dateFormatting": {},
@@ -333,12 +333,12 @@
"@last30Days": {},
"allowMissingValues": "Autoriser les valeurs manquantes",
"@allowMissingValues": {},
- "enterTimeFormatTxt3": "Rappel amical : utiliser des chaines de formatage plus courtes ou plus longues ne modifieront pas la largeur des colonnes de table par magie, ce qui pourrait générer des retours à la ligne inattendus ou que du texte n'apparaisse pas.",
+ "enterTimeFormatTxt3": "Rappel amical : utiliser des chaines de formatage plus courtes ou plus longues ne modifieront pas la largeur des colonnes de table par magie, ce qui pourrait générer des retours à la ligne inattendus ou que du texte n''apparaisse pas.",
"@enterTimeFormatTxt3": {},
"custom": "Personnalisé",
"@custom": {},
"language": "Langue",
"@language": {},
- "errTimeAfterNow": "L'heure choisie est dans le futur. Nous avons automatiquement repositionné à l'heure courante. Vous pouvez désactiver ce comportement dans les paramètres !",
+ "errTimeAfterNow": "L''heure choisie est dans le futur. Nous avons automatiquement repositionné à l''heure courante. Vous pouvez désactiver ce comportement dans les paramètres !",
"@errTimeAfterNow": {}
}
lib/l10n/app_nb.arb
@@ -322,7 +322,7 @@
"@enterTimeFormatTxt3": {},
"enterTimeFormatTxt1": "En formateringsstreng er en miks av predefinert ICU/Skeleton -strenger og all annen tekst du vil inkludere.",
"@enterTimeFormatTxt1": {},
- "exportWarnConfigNotImportable": "Gjør eksportoppsettet importerbart ved å sette eksporttypen til \\\"CSV\\\", skru på overskrift, inkluder feltene 'diastolic', 'systolic', 'pulse', 'notes', sammen med ett av de tilgjengelige tidsformatene.",
+ "exportWarnConfigNotImportable": "Gjør eksportoppsettet importerbart ved å sette eksporttypen til \\\"CSV\\\", skru på overskrift, inkluder feltene ''diastolic'', ''systolic'', ''pulse'', ''notes'', sammen med ett av de tilgjengelige tidsformatene.",
"@exportWarnConfigNotImportable": {},
"allowMissingValues": "Tillat manglende verdier",
"@allowMissingValues": {},
lib/screens/subsettings/export_column_data.dart
@@ -1,5 +1,6 @@
import 'package:blood_pressure_app/model/blood_pressure.dart';
import 'package:blood_pressure_app/model/export_options.dart';
+import 'package:blood_pressure_app/screens/subsettings/export_field_format_documentation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@@ -61,7 +62,7 @@ class _EditExportColumnPageState extends State<EditExportColumnPage> {
TextFormField(
key: const Key('displayName'),
initialValue: _displayName,
- decoration: InputDecoration(hintText: localizations.displayTitle),
+ decoration: InputDecoration(label: Text(localizations.displayTitle)),
onChanged: (String? value) {
if (value != null && value.isNotEmpty) {
setState(() {
@@ -82,7 +83,7 @@ class _EditExportColumnPageState extends State<EditExportColumnPage> {
TextFormField(
key: Key('internalName$_internalNameKeyNr'), // it should update when display name is changed without unfocussing on edit
initialValue: _internalName,
- decoration: InputDecoration(hintText: localizations.internalName),
+ decoration: InputDecoration(label: Text(localizations.internalName)),
enabled: (widget.initialInternalName == null),
validator: (String? value) {
if (value == null || value.isEmpty || RegExp(r'[^A-Za-z0-9]').hasMatch(value)) {
@@ -102,12 +103,21 @@ class _EditExportColumnPageState extends State<EditExportColumnPage> {
TextFormField( // TODO: documentation
key: const Key('formatPattern'),
initialValue: _formatPattern,
- decoration: InputDecoration(hintText: localizations.fieldFormat),
+ decoration: InputDecoration(
+ label: Text(localizations.fieldFormat),
+ suffixIcon: IconButton(
+ onPressed: () {
+ Navigator.of(context).push(MaterialPageRoute(
+ builder: (context) => InformationScreen(text: localizations.exportFieldFormatDocumentation)));
+ },
+ icon: const Icon(Icons.info_outline)
+ ),
+ ),
maxLines: 6,
minLines: 1,
validator: (String? value) {
if (value == null || value.isEmpty) {
- return AppLocalizations.of(context)!.errNoValue;
+ return localizations.errNoValue;
} else if (_internalName != null && _displayName != null) {
try {
final column = ExportColumn(internalName: _internalName!, columnTitle: _displayName!, formatPattern: value);
@@ -143,13 +153,13 @@ class _EditExportColumnPageState extends State<EditExportColumnPage> {
Navigator.of(context).pop();
},
- child: Text(AppLocalizations.of(context)!.btnCancel)
+ child: Text(localizations.btnCancel)
),
const Spacer(),
FilledButton.icon(
key: const Key('btnSave'),
icon: const Icon(Icons.save),
- label: Text(AppLocalizations.of(context)!.btnSave),
+ label: Text(localizations.btnSave),
onPressed: (widget.editable) ? (() async {
if (_formKey.currentState?.validate() ?? false) {
widget.onValidSubmit(ExportColumn(
lib/screens/subsettings/export_field_format_documentation.dart
@@ -0,0 +1,45 @@
+import 'package:blood_pressure_app/screens/subsettings/time_formats_explainer.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_markdown/flutter_markdown.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class InformationScreen extends StatelessWidget {
+ /// text in markdown format
+ final String text;
+ const InformationScreen({super.key, required this.text});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ backgroundColor: Theme.of(context).primaryColor,
+ ),
+ body: Container(
+ padding: const EdgeInsets.all(10),
+ child: Markdown(
+ selectable: true,
+ onTapLink: (text, destination, title) async {
+ if (destination == null) {
+ return;
+ }
+ if (destination.startsWith('http://') || destination.startsWith('https://')) {
+ final url = Uri.tryParse(destination);
+ if (url != null && await canLaunchUrl(url)) {
+ launchUrl(url);
+ return;
+ }
+ } else if (destination.startsWith('screen://')) {
+ switch (destination.split('//')[1]) {
+ case 'TimeFormattingHelp':
+ Navigator.of(context).push(MaterialPageRoute(builder: (context) => const TimeFormattingHelp()));
+ return;
+ }
+ }
+ assert(false, 'Markdown contains invalid URL');
+ },
+ data: text
+ ),
+ )
+ );
+ }
+}
\ No newline at end of file
lib/screens/subsettings/time_formats_explainer.dart
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
-import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class TimeFormattingHelp extends StatelessWidget {
const TimeFormattingHelp({super.key});
@@ -46,7 +45,6 @@ class TimeFormattingHelp extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
- title: Text(AppLocalizations.of(context)!.dateFormatting),
backgroundColor: Theme.of(context).primaryColor,
),
body: Container(
l10n.yaml
@@ -1,4 +1,5 @@
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
-untranslated-messages-file: l10n_errors.txt
\ No newline at end of file
+untranslated-messages-file: l10n_errors.txt
+use-escaping: true
\ No newline at end of file
pubspec.lock
@@ -251,6 +251,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ flutter_markdown:
+ dependency: "direct main"
+ description:
+ name: flutter_markdown
+ sha256: "4b1bfbb802d76320a1a46d9ce984106135093efd9d969765d07c2125af107bdf"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.6.17"
flutter_material_color_picker:
dependency: "direct main"
description:
@@ -357,6 +365,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.0"
+ markdown:
+ dependency: transitive
+ description:
+ name: markdown
+ sha256: acf35edccc0463a9d7384e437c015a3535772e09714cf60e07eeef3a15870dcd
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.1.1"
matcher:
dependency: transitive
description:
pubspec.yaml
@@ -32,6 +32,7 @@ dependencies:
jsaver: ^1.2.0
function_tree: ^0.8.13
badges: ^3.1.1
+ flutter_markdown: ^0.6.17
dev_dependencies:
flutter_test: