Commit dbfa86e
Changed files (6)
lib
components
screens
lib/components/input_dialoge.dart
@@ -0,0 +1,76 @@
+import 'package:blood_pressure_app/model/settings_store.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:provider/provider.dart';
+
+class InputDialoge extends StatefulWidget {
+ final String hintText;
+ final void Function(String text) onSubmit;
+ final List<TextInputFormatter>? inputFormatters;
+ final TextInputType? keyboardType;
+
+ const InputDialoge({super.key, required this.hintText, required this.onSubmit, this.inputFormatters, this.keyboardType});
+
+ @override
+ State<InputDialoge> createState() => _InputDialogeState();
+}
+
+class _InputDialogeState extends State<InputDialoge> {
+ final formKey = GlobalKey<FormState>();
+ final controller = TextEditingController();
+
+ @override
+ void dispose() {
+ // Clean up the controller when the widget is disposed.
+ controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return AlertDialog(
+ content: TextFormField(
+ key: formKey,
+ controller: controller,
+ inputFormatters: widget.inputFormatters,
+ keyboardType: widget.keyboardType,
+ decoration: InputDecoration(hintText: widget.hintText),
+ ),
+ actions: [
+ Consumer<Settings>(builder: (context, settings, child) {
+ return ElevatedButton(
+ onPressed: () {
+ widget.onSubmit(controller.text);
+ },
+ child: Text(AppLocalizations.of(context)!.btnConfirm)
+ );
+ }),
+
+ ],
+ );
+ }
+}
+
+class NumberInputDialoge extends StatelessWidget {
+ final String hintText;
+ final void Function(int text) onParsableSubmit;
+
+ const NumberInputDialoge({super.key, required this.hintText, required this.onParsableSubmit});
+
+ @override
+ Widget build(BuildContext context) {
+ return InputDialoge(
+ hintText: hintText,
+ inputFormatters: [FilteringTextInputFormatter.digitsOnly],
+ keyboardType: TextInputType.number,
+ onSubmit: (text) {
+ if (text.isEmpty || (int.tryParse(text) == null)) {
+ return;
+ }
+ int value = int.parse(text);
+ onParsableSubmit(value);
+ }
+ );
+ }
+}
lib/model/ram_only_implementations.dart
@@ -508,6 +508,19 @@ class RamSettings extends ChangeNotifier implements Settings {
notifyListeners();
}
+ Iterable<int> _horizontalGraphLines = [];
+
+ @override
+ Iterable<int> get horizontalGraphLines {
+ return _horizontalGraphLines;
+ }
+
+ @override
+ set horizontalGraphLines(Iterable<int> value) {
+ _horizontalGraphLines = value;
+ notifyListeners();
+ }
+
@override
void changeStepSize(TimeStep value) {
graphStepSize = value;
lib/model/settings_store.dart
@@ -614,6 +614,16 @@ class Settings extends ChangeNotifier {
_prefs.setStringList('exportItemsPdf', value);
notifyListeners();
}
+
+ Iterable<int> get horizontalGraphLines {
+ final linesStr = _prefs.getStringList('horizontalGraphLines') ?? [];
+ return linesStr.map((e) => int.parse(e));
+ }
+
+ set horizontalGraphLines(Iterable<int> value) {
+ _prefs.setStringList('horizontalGraphLines', value.map((e) => e.toString()).toList());
+ notifyListeners();
+ }
}
enum TimeStep {
lib/screens/subsettings/graph_markings.dart
@@ -0,0 +1,61 @@
+import 'package:blood_pressure_app/components/input_dialoge.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import '../../model/settings_store.dart';
+
+class GraphMarkingsScreen extends StatelessWidget {
+ const GraphMarkingsScreen({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ backgroundColor: Theme.of(context).primaryColor,
+ ),
+ body: Center(child: Consumer<Settings>(
+ builder: (context, settings, child) {
+ final lines = settings.horizontalGraphLines.toList();
+ return Container(
+ padding: const EdgeInsets.all(20.0),
+ child: ListView.builder(
+ itemCount: lines.length+1,
+ itemBuilder: (context, i) {
+ if(i == 0) {
+ return Row(
+ children: [
+ Text('Horizontal Lines'), // TODO localize, implement
+ const Spacer(),
+ IconButton(
+ icon: const Icon(Icons.add),
+ onPressed: () {
+ showDialog(
+ context: context,
+ builder: (context) => NumberInputDialoge(
+ hintText: 'hintText',
+ onParsableSubmit: (value) {
+ lines.add(value);
+ Navigator.of(context).pop();
+ }
+ ),
+ );
+ },
+ )
+ ],
+ );
+ }
+ return Row(
+ children: [
+ Text(lines[i-1].toString()),
+ Spacer(),
+ Icon(Icons.delete)
+ ],
+ );
+ }
+ )
+ );
+ }),
+ ),
+ );
+ }
+}
lib/screens/add_measurement.dart
@@ -135,7 +135,7 @@ class _AddMeasurementPageState extends State<AddMeasurementPage> {
key: const Key('txtPul'),
initialValue: (_pulse ?? '').toString(),
minLines: 1,
- maxLines: 4,
+ maxLines: 4, // TODO: check if this shouldn't be part of note input
hintText: AppLocalizations.of(context)!.pulLong,
basicValidation: !settings.allowMissingValues,
preValidation: (v) => _pulse = int.tryParse(v ?? ''),
lib/screens/settings.dart
@@ -1,10 +1,12 @@
import 'package:blood_pressure_app/components/consistent_future_builder.dart';
+import 'package:blood_pressure_app/components/input_dialoge.dart';
import 'package:blood_pressure_app/components/settings_widgets.dart';
import 'package:blood_pressure_app/model/blood_pressure.dart';
import 'package:blood_pressure_app/model/iso_lang_names.dart';
import 'package:blood_pressure_app/model/settings_store.dart';
import 'package:blood_pressure_app/screens/subsettings/enter_timeformat.dart';
import 'package:blood_pressure_app/screens/subsettings/export_import_screen.dart';
+import 'package:blood_pressure_app/screens/subsettings/graph_markings.dart';
import 'package:blood_pressure_app/screens/subsettings/version.dart';
import 'package:blood_pressure_app/screens/subsettings/warn_about.dart';
import 'package:flutter/material.dart';
@@ -28,22 +30,11 @@ class SettingsPage extends StatelessWidget {
return ListView(
children: [
SettingsSection(title: Text(AppLocalizations.of(context)!.layout), children: [
- SwitchSettingsTile(
- key: const Key('allowManualTimeInput'),
- initialValue: settings.allowManualTimeInput,
- onToggle: (value) {
- settings.allowManualTimeInput = value;
- },
- leading: const Icon(Icons.details),
- title: Text(AppLocalizations.of(context)!.allowManualTimeInput)),
SettingsTile(
key: const Key('EnterTimeFormatScreen'),
title: Text(AppLocalizations.of(context)!.enterTimeFormatScreen),
leading: const Icon(Icons.schedule),
- trailing: Icon(
- Icons.arrow_forward_ios,
- color: Theme.of(context).highlightColor,
- ),
+ trailing: const Icon(Icons.arrow_forward_ios),
description: Text(settings.dateFormatString),
onPressed: (context) {
Navigator.push(
@@ -80,6 +71,11 @@ class SettingsPage extends StatelessWidget {
}
},
),
+ ColorSelectionSettingsTile(
+ key: const Key('accentColor'),
+ onMainColorChanged: (color) => settings.accentColor = createMaterialColor((color ?? Colors.teal).value),
+ initialColor: settings.accentColor,
+ title: Text(AppLocalizations.of(context)!.accentColor)),
DropDownSettingsTile<Locale?>(
key: const Key('language'),
leading: const Icon(Icons.language),
@@ -143,52 +139,55 @@ class SettingsPage extends StatelessWidget {
stepSize: 1,
),
ColorSelectionSettingsTile(
- key: const Key('accentColor'),
- onMainColorChanged: (color) =>
- settings.accentColor = createMaterialColor((color ?? Colors.teal).value),
- initialColor: settings.accentColor,
- title: Text(AppLocalizations.of(context)!.accentColor)),
- ColorSelectionSettingsTile(
- key: const Key('sysColor'),
- onMainColorChanged: (color) => settings.sysColor = createMaterialColor((color ?? Colors.green).value),
- initialColor: settings.sysColor,
+ key: const Key('sysColor'),
+ onMainColorChanged: (color) => settings.sysColor = createMaterialColor((color ?? Colors.green).value),
+ initialColor: settings.sysColor,
title: Text(AppLocalizations.of(context)!.sysColor)),
ColorSelectionSettingsTile(
- key: const Key('diaColor'),
- onMainColorChanged: (color) => settings.diaColor = createMaterialColor((color ?? Colors.teal).value),
- initialColor: settings.diaColor,
- title: Text(AppLocalizations.of(context)!.diaColor)),
+ key: const Key('diaColor'),
+ onMainColorChanged: (color) => settings.diaColor = createMaterialColor((color ?? Colors.teal).value),
+ initialColor: settings.diaColor,
+ title: Text(AppLocalizations.of(context)!.diaColor)),
ColorSelectionSettingsTile(
- key: const Key('pulColor'),
- onMainColorChanged: (color) => settings.pulColor = createMaterialColor((color ?? Colors.red).value),
- initialColor: settings.pulColor,
- title: Text(AppLocalizations.of(context)!.pulColor)),
+ key: const Key('pulColor'),
+ onMainColorChanged: (color) => settings.pulColor = createMaterialColor((color ?? Colors.red).value),
+ initialColor: settings.pulColor,
+ title: Text(AppLocalizations.of(context)!.pulColor)),
]),
+
SettingsSection(title: Text(AppLocalizations.of(context)!.behavior), children: [
SwitchSettingsTile(
- key: const Key('validateInputs'),
- initialValue: settings.validateInputs,
- title: Text(AppLocalizations.of(context)!.validateInputs),
- leading: const Icon(Icons.edit),
- onToggle: (value) {
- settings.validateInputs = value;
- }),
+ key: const Key('allowManualTimeInput'),
+ initialValue: settings.allowManualTimeInput,
+ onToggle: (value) {
+ settings.allowManualTimeInput = value;
+ },
+ leading: const Icon(Icons.details),
+ title: Text(AppLocalizations.of(context)!.allowManualTimeInput)),
+ SwitchSettingsTile(
+ key: const Key('validateInputs'),
+ initialValue: settings.validateInputs,
+ title: Text(AppLocalizations.of(context)!.validateInputs),
+ leading: const Icon(Icons.edit),
+ onToggle: (value) {
+ settings.validateInputs = value;
+ }),
SwitchSettingsTile(
- key: const Key('allowMissingValues'),
- initialValue: settings.allowMissingValues,
- title: Text(AppLocalizations.of(context)!.allowMissingValues),
- leading: const Icon(Icons.report_off_outlined),
- onToggle: (value) {
- settings.allowMissingValues = value;
- }),
+ key: const Key('allowMissingValues'),
+ initialValue: settings.allowMissingValues,
+ title: Text(AppLocalizations.of(context)!.allowMissingValues),
+ leading: const Icon(Icons.report_off_outlined),
+ onToggle: (value) {
+ settings.allowMissingValues = value;
+ }),
SwitchSettingsTile(
- key: const Key('confirmDeletion'),
- initialValue: settings.confirmDeletion,
- title: Text(AppLocalizations.of(context)!.confirmDeletion),
- leading: const Icon(Icons.check),
- onToggle: (value) {
- settings.confirmDeletion = value;
- }),
+ key: const Key('confirmDeletion'),
+ initialValue: settings.confirmDeletion,
+ title: Text(AppLocalizations.of(context)!.confirmDeletion),
+ leading: const Icon(Icons.check),
+ onToggle: (value) {
+ settings.confirmDeletion = value;
+ }),
InputSettingsTile(
key: const Key('sysWarn'),
title: Text(AppLocalizations.of(context)!.sysWarn),
@@ -228,7 +227,19 @@ class SettingsPage extends StatelessWidget {
onPressed: (context) {
showDialog(
context: context,
- builder: (context) => const DetermineAgeValues(),
+ builder: (context) => NumberInputDialoge(
+ hintText: AppLocalizations.of(context)!.age,
+ onParsableSubmit: (age) {
+ settings.sysWarn = BloodPressureWarnValues.getUpperSysWarnValue(age);
+ settings.diaWarn = BloodPressureWarnValues.getUpperDiaWarnValue(age);
+ Navigator.of(context).pop();
+ Navigator.of(context).pop();
+ Navigator.push(
+ context,
+ MaterialPageRoute(builder: (context) => const SettingsPage()),
+ );
+ },
+ )
);
},
),
@@ -237,6 +248,7 @@ class SettingsPage extends StatelessWidget {
title: Text(AppLocalizations.of(context)!.aboutWarnValuesScreen),
description: Text(AppLocalizations.of(context)!.aboutWarnValuesScreenDesc),
leading: const Icon(Icons.info_outline),
+ trailing: const Icon(Icons.arrow_forward_ios),
onPressed: (context) {
Navigator.push(
context,
@@ -244,6 +256,19 @@ class SettingsPage extends StatelessWidget {
);
}
),
+ SettingsTile(
+ key: const Key('GraphMarkingsScreen'),
+ title: Text(AppLocalizations.of(context)!.text),
+ description: Text(AppLocalizations.of(context)!.text), // TODO desc u title
+ leading: const Icon(Icons.legend_toggle_outlined),
+ trailing: const Icon(Icons.arrow_forward_ios),
+ onPressed: (context) {
+ Navigator.push(
+ context,
+ MaterialPageRoute(builder: (context) => const GraphMarkingsScreen()),
+ );
+ }
+ ),
SwitchSettingsTile(
title: Text(AppLocalizations.of(context)!.drawRegressionLines),
leading: const Icon(Icons.trending_down_outlined),
@@ -315,10 +340,7 @@ class SettingsPage extends StatelessWidget {
key: const Key('licenses'),
title: Text(AppLocalizations.of(context)!.licenses),
leading: const Icon(Icons.policy_outlined),
- trailing: Icon(
- Icons.arrow_forward_ios,
- color: Theme.of(context).highlightColor,
- ),
+ trailing: const Icon(Icons.arrow_forward_ios),
onPressed: (context) {
showLicensePage(context: context);
},
@@ -330,56 +352,3 @@ class SettingsPage extends StatelessWidget {
);
}
}
-
-class DetermineAgeValues extends StatefulWidget {
- const DetermineAgeValues({super.key});
-
- @override
- State<DetermineAgeValues> createState() => _DetermineAgeValuesState();
-}
-
-class _DetermineAgeValuesState extends State<DetermineAgeValues> {
- final formKey = GlobalKey<FormState>();
- final controller = TextEditingController();
-
- @override
- void dispose() {
- // Clean up the controller when the widget is disposed.
- controller.dispose();
- super.dispose();
- }
-
- @override
- Widget build(BuildContext context) {
- return AlertDialog(
- content: TextFormField(
- key: formKey,
- controller: controller,
- inputFormatters: [FilteringTextInputFormatter.digitsOnly],
- decoration: InputDecoration(hintText: AppLocalizations.of(context)!.age),
- ),
- actions: [
- Consumer<Settings>(builder: (context, settings, child) {
- return ElevatedButton(
- onPressed: () {
- if (controller.text.isEmpty || (int.tryParse(controller.text) == null)) {
- return;
- }
- int age = int.parse(controller.text);
- settings.sysWarn = BloodPressureWarnValues.getUpperSysWarnValue(age);
- settings.diaWarn = BloodPressureWarnValues.getUpperDiaWarnValue(age);
- Navigator.of(context).pop();
- Navigator.of(context).pop();
- Navigator.push(
- context,
- MaterialPageRoute(builder: (context) => const SettingsPage()),
- );
- },
- child: Text(AppLocalizations.of(context)!.btnConfirm)
- );
- }),
-
- ],
- );
- }
-}