Commit a312f13
Changed files (7)
lib
test
ui
components
lib/components/dialoges/add_export_column_dialoge.dart
@@ -1,3 +1,4 @@
+import 'package:blood_pressure_app/components/dialoges/fullscreen_dialoge.dart';
import 'package:blood_pressure_app/components/measurement_list/measurement_list_entry.dart';
import 'package:blood_pressure_app/model/blood_pressure/record.dart';
import 'package:blood_pressure_app/model/export_import/column.dart';
@@ -13,7 +14,10 @@ import 'package:intl/intl.dart';
/// For further documentation please refer to [showAddExportColumnDialoge].
class AddExportColumnDialoge extends StatefulWidget {
/// Create a widget for creating and editing a [UserColumn].
- const AddExportColumnDialoge({super.key, this.initialColumn, required this.settings});
+ const AddExportColumnDialoge({super.key,
+ this.initialColumn,
+ required this.settings,
+ });
final ExportColumn? initialColumn;
@@ -71,39 +75,10 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> with Si
@override
Widget build(BuildContext context) {
final localizations = AppLocalizations.of(context)!;
- return Scaffold(
- appBar: AppBar(
- forceMaterialTransparency: true,
- leading: IconButton(
- onPressed: () => Navigator.of(context).pop(null),
- icon: const Icon(Icons.close)
- ),
- actions: [
- TextButton(
- onPressed: () {
- if (formKey.currentState?.validate() ?? false) {
- formKey.currentState!.save();
- late ExportColumn column;
- if (type == _FormatterType.record) {
- assert(recordPattern != null, 'validator should check');
- column = (widget.initialColumn != null)
- ? UserColumn.explicit(widget.initialColumn!.internalIdentifier, csvTitle, recordPattern!)
- : UserColumn(csvTitle, csvTitle, recordPattern!);
- Navigator.pop(context, column);
- } else {
- assert(type == _FormatterType.time);
- assert(timePattern != null, 'validator should check');
- column = (widget.initialColumn != null)
- ? TimeColumn.explicit(widget.initialColumn!.internalIdentifier, csvTitle, timePattern!)
- : TimeColumn(csvTitle, timePattern!);
- Navigator.pop(context, column);
- }
- }
- },
- child: Text(localizations.btnSave)
- )
- ],
- ),
+ return FullscreenDialoge(
+ actionButtonText: localizations.btnSave,
+ onActionButtonPressed: _saveForm,
+ bottomAppBar: widget.settings.bottomAppBars,
body: Form(
key: formKey,
child: ListView(
@@ -197,7 +172,6 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> with Si
),
],
),
-
),
);
}
@@ -272,6 +246,28 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> with Si
enabledBorder: border,
);
}
+
+ void _saveForm() {
+ if (formKey.currentState?.validate() ?? false) {
+ formKey.currentState!.save();
+ late ExportColumn column;
+ if (type == _FormatterType.record) {
+ assert(recordPattern != null, 'validator should check');
+ column = (widget.initialColumn != null)
+ ? UserColumn.explicit(widget.initialColumn!.internalIdentifier, csvTitle, recordPattern!)
+ : UserColumn(csvTitle, csvTitle, recordPattern!);
+ Navigator.pop(context, column);
+ } else {
+ assert(type == _FormatterType.time);
+ assert(timePattern != null, 'validator should check');
+ column = (widget.initialColumn != null)
+ ? TimeColumn.explicit(widget.initialColumn!.internalIdentifier, csvTitle, timePattern!)
+ : TimeColumn(csvTitle, timePattern!);
+ Navigator.pop(context, column);
+ }
+ }
+ }
+
}
enum _FormatterType {
lib/components/dialoges/add_measurement_dialoge.dart
@@ -1,6 +1,7 @@
import 'dart:math';
import 'package:blood_pressure_app/components/date_time_picker.dart';
+import 'package:blood_pressure_app/components/dialoges/fullscreen_dialoge.dart';
import 'package:blood_pressure_app/components/settings/settings_widgets.dart';
import 'package:blood_pressure_app/model/blood_pressure/needle_pin.dart';
import 'package:blood_pressure_app/model/blood_pressure/record.dart';
@@ -15,10 +16,10 @@ class AddMeasurementDialoge extends StatefulWidget {
/// Create a input mask for entering measurements.
///
/// This is usually created through the [showAddMeasurementDialoge] function.
- const AddMeasurementDialoge(
- {super.key,
- required this.settings,
- this.initialRecord});
+ const AddMeasurementDialoge({super.key,
+ required this.settings,
+ this.initialRecord,
+ });
/// Settings are followed by the dialoge.
final Settings settings;
@@ -190,26 +191,16 @@ class _AddMeasurementDialogeState extends State<AddMeasurementDialoge> {
@override
Widget build(BuildContext context) {
final localizations = AppLocalizations.of(context)!;
- return Scaffold(
- appBar: AppBar(
- forceMaterialTransparency: true,
- leading: IconButton(
- onPressed: () => Navigator.of(context).pop(null),
- icon: const Icon(Icons.close)
- ),
- actions: [
- TextButton(
- onPressed: () {
- if (formKey.currentState?.validate() ?? false) {
- formKey.currentState?.save();
- final record = BloodPressureRecord(time, systolic, diastolic, pulse, notes ?? '', needlePin: needlePin);
- Navigator.of(context).pop(record);
- }
- },
- child: Text(localizations.btnSave)
- )
- ],
- ),
+ return FullscreenDialoge(
+ onActionButtonPressed: () {
+ if (formKey.currentState?.validate() ?? false) {
+ formKey.currentState?.save();
+ final record = BloodPressureRecord(time, systolic, diastolic, pulse, notes ?? '', needlePin: needlePin);
+ Navigator.of(context).pop(record);
+ }
+ },
+ actionButtonText: localizations.btnSave,
+ bottomAppBar: widget.settings.bottomAppBars,
body: Form(
key: formKey,
child: ListView(
lib/components/dialoges/enter_timeformat_dialoge.dart
@@ -1,13 +1,18 @@
+import 'package:blood_pressure_app/components/dialoges/fullscreen_dialoge.dart';
import 'package:blood_pressure_app/screens/subsettings/export_import/export_field_format_documentation_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:intl/intl.dart';
-/// Dialoge that explains the time format and pops the context with either null or a time format string.
+/// Fullscreen dialoge that explains the time format and pops the context with either null or a time format string.
class EnterTimeFormatDialoge extends StatefulWidget {
/// Create dialoge for entering time formats as used by the [DateFormat] class.
- const EnterTimeFormatDialoge({super.key, required this.initialValue, this.previewTime});
+ const EnterTimeFormatDialoge({super.key,
+ required this.initialValue,
+ this.previewTime,
+ this.bottomAppBars = false
+ });
/// Text that is initially in time format field.
final String initialValue;
@@ -17,6 +22,8 @@ class EnterTimeFormatDialoge extends StatefulWidget {
/// When previewTime is null [DateTime.now] will be used.
final DateTime? previewTime;
+ final bool bottomAppBars;
+
@override
State<EnterTimeFormatDialoge> createState() => _EnterTimeFormatDialogeState();
}
@@ -43,26 +50,14 @@ class _EnterTimeFormatDialogeState extends State<EnterTimeFormatDialoge> {
@override
Widget build(BuildContext context) {
final localizations = AppLocalizations.of(context)!;
- return Scaffold(
- appBar: AppBar(
- forceMaterialTransparency: true,
- leading: IconButton(
- onPressed: () {
- Navigator.of(context).pop(null);
- },
- icon: const Icon(Icons.close)
- ),
- actions: [
- TextButton(
- onPressed: () {
- if(timeFormatFieldController.text.isNotEmpty) {
- Navigator.of(context).pop(timeFormatFieldController.text);
- }
- },
- child: Text(localizations.btnSave)
- )
- ],
- ),
+ return FullscreenDialoge(
+ actionButtonText: localizations.btnSave,
+ bottomAppBar: widget.bottomAppBars,
+ onActionButtonPressed: () {
+ if(timeFormatFieldController.text.isNotEmpty) {
+ Navigator.of(context).pop(timeFormatFieldController.text);
+ }
+ },
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(24),
@@ -98,7 +93,7 @@ class _EnterTimeFormatDialogeState extends State<EnterTimeFormatDialoge> {
/// Shows a dialoge that explains the ICU DateTime format and allows editing [initialTimeFormat] with a preview.
///
/// When canceled null is returned.
-Future<String?> showTimeFormatPickerDialoge(BuildContext context, String initialTimeFormat) =>
- showDialog<String?>(context: context, builder: (context) => Dialog.fullscreen(
- child: EnterTimeFormatDialoge(initialValue: initialTimeFormat),
- ));
\ No newline at end of file
+Future<String?> showTimeFormatPickerDialoge(BuildContext context, String initialTimeFormat, bool bottomAppBars) =>
+ showDialog<String?>(context: context, builder: (context) => Dialog.fullscreen(
+ child: EnterTimeFormatDialoge(initialValue: initialTimeFormat, bottomAppBars: bottomAppBars,),
+ ));
\ No newline at end of file
lib/components/dialoges/input_dialoge.dart
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
-/// Dialoge for prompting single value input from the user.
+/// Alert dialoge for prompting single value input from the user.
class InputDialoge extends StatefulWidget {
/// Creates an [AlertDialog] with an text input field.
///
lib/screens/settings_screen.dart
@@ -45,7 +45,9 @@ class SettingsPage extends StatelessWidget {
leading: const Icon(Icons.schedule),
trailing: const Icon(Icons.arrow_forward_ios),
onTap: () async {
- final pickedFormat = await showTimeFormatPickerDialoge(context, settings.dateFormatString);
+ final pickedFormat = await showTimeFormatPickerDialoge(context,
+ settings.dateFormatString,
+ settings.bottomAppBars);
if (pickedFormat != null) {
settings.dateFormatString = pickedFormat;
}
lib/main.dart
@@ -80,12 +80,11 @@ class AppRoot extends StatelessWidget {
return AppLocalizations.of(context)!.title;
},
theme: ThemeData(
- colorScheme: ColorScheme.fromSeed(
- seedColor: settings.accentColor,
- brightness: Brightness.light,
- ),
-
- useMaterial3: true
+ colorScheme: ColorScheme.fromSeed(
+ seedColor: settings.accentColor,
+ brightness: Brightness.light,
+ ),
+ useMaterial3: true,
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
test/ui/components/enter_timeformat_dialoge_test.dart
@@ -57,7 +57,7 @@ void main() {
testWidgets('should return null on close', (widgetTester) async {
String? result = 'notnull';
await loadDialoge(widgetTester,
- (context) async => result = await showTimeFormatPickerDialoge(context, 'yyyy-MM-dd HH:mm'));
+ (context) async => result = await showTimeFormatPickerDialoge(context, 'yyyy-MM-dd HH:mm', false));
expect(find.byIcon(Icons.close), findsOneWidget);
await widgetTester.tap(find.byIcon(Icons.close));
@@ -68,7 +68,7 @@ void main() {
testWidgets('should return value on save', (widgetTester) async {
String? result;
await loadDialoge(widgetTester,
- (context) async => result = await showTimeFormatPickerDialoge(context, 'yyyy-MM-dd HH:mm'));
+ (context) async => result = await showTimeFormatPickerDialoge(context, 'yyyy-MM-dd HH:mm', false));
expect(find.text('SAVE'), findsOneWidget);
await widgetTester.tap(find.text('SAVE'));
@@ -79,7 +79,7 @@ void main() {
testWidgets('should return modified value on save', (widgetTester) async {
String? result;
await loadDialoge(widgetTester,
- (context) async => result = await showTimeFormatPickerDialoge(context, 'yyyy-MM-dd HH:mm'));
+ (context) async => result = await showTimeFormatPickerDialoge(context, 'yyyy-MM-dd HH:mm', false));
await widgetTester.enterText(find.byType(TextField), 'test text!');
await widgetTester.pumpAndSettle();