Commit 2577acb

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2024-01-13 09:44:42
manually address important issues highlighted by analysis
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent 29e9919
Changed files (82)
lib
test
lib/components/dialoges/add_export_column_dialoge.dart
@@ -19,18 +19,24 @@ class AddExportColumnDialoge extends StatefulWidget {
     required this.settings,
   });
 
+  /// Prefills the form to a submitted state.
+  ///
+  /// When this is null it is assumed creating a new column is intended.
   final ExportColumn? initialColumn;
 
+  /// Settings to determine general behavior.
   final Settings settings;
 
   @override
   State<AddExportColumnDialoge> createState() => _AddExportColumnDialogeState();
 }
 
-class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> with SingleTickerProviderStateMixin {
+class _AddExportColumnDialogeState extends State<AddExportColumnDialoge>
+    with SingleTickerProviderStateMixin {
   final formKey = GlobalKey<FormState>();
 
-  /// Csv column title used to compute internal identifier in case [widget.initialColumn] is null.
+  /// Csv column title used to compute internal identifier in case
+  /// [AddExportColumnDialoge.initialColumn] is null.
   late String csvTitle;
 
   /// Pattern for record formatting preview and for column creation on save.
@@ -82,7 +88,8 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> with Si
       body: GestureDetector(
         onHorizontalDragEnd: (details) {
           if (details.primaryVelocity == null) return;
-          if (details.primaryVelocity! < -500 && type == _FormatterType.record) {
+          if (details.primaryVelocity! < -500
+              && type == _FormatterType.record) {
             _changeMode(_FormatterType.time);
           }
           if (details.primaryVelocity! > 500 && type == _FormatterType.time) {
@@ -98,7 +105,9 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> with Si
                 decoration: InputDecoration(
                   labelText: localizations.csvTitle,
                 ),
-                validator: (value) => (value != null && value.isNotEmpty) ? null : localizations.errNoValue,
+                validator: (value) => (value != null && value.isNotEmpty)
+                    ? null
+                    : localizations.errNoValue,
                 onSaved: (value) => setState(() {csvTitle = value!;}),
               ),
               const SizedBox(height: 8,),
@@ -152,18 +161,35 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> with Si
                   borderRadius: BorderRadius.circular(20),
                 ),
                 child: (){
-                    final record = BloodPressureRecord(DateTime.now(), 123, 78, 65, 'test note');
-                    final formatter = (type == _FormatterType.record) ? ScriptedFormatter(recordPattern ?? '')
+                    final record = BloodPressureRecord(
+                      DateTime.now(),
+                      123, 78, 65,
+                      'test note',
+                    );
+                    final formatter = (type == _FormatterType.record)
+                        ? ScriptedFormatter(recordPattern ?? '')
                         : ScriptedTimeFormatter(timePattern ?? '');
                     final text = formatter.encode(record);
                     final decoded = formatter.decode(text);
                     return Column(
                       children: [
-                        if (type == _FormatterType.record) MeasurementListRow(record: record, settings: widget.settings,) else Text(DateFormat('MMM d, y - h:m.s').format(record.creationTime)),
+                        if (type == _FormatterType.record)
+                          MeasurementListRow(
+                            record: record,
+                            settings: widget.settings,
+                          ) else Text(
+                            DateFormat('MMM d, y - h:m.s')
+                                .format(record.creationTime),
+                        ),
                         const SizedBox(height: 8,),
                         const Icon(Icons.arrow_downward),
                         const SizedBox(height: 8,),
-                        if (text.isNotEmpty) Text(text) else Text(localizations.errNoValue, style: const TextStyle(fontStyle: FontStyle.italic),),
+                        if (text.isNotEmpty)
+                          Text(text)
+                        else
+                          Text(localizations.errNoValue,
+                            style: const TextStyle(fontStyle: FontStyle.italic),
+                          ),
                         const SizedBox(height: 8,),
                         const Icon(Icons.arrow_downward),
                         const SizedBox(height: 8,),
@@ -196,7 +222,10 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> with Si
             suffixIcon: IconButton(
                 onPressed: () {
                   Navigator.of(context).push(MaterialPageRoute(
-                      builder: (context) => InformationScreen(text: inputDocumentation),),);
+                    builder: (context) => InformationScreen(
+                        text: inputDocumentation,
+                    ),
+                  ),);
                 },
                 icon: const Icon(Icons.info_outline),
             ),
@@ -206,31 +235,38 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> with Si
       ],
     );
 
-  Column _createRecordFormatInput(AppLocalizations localizations, BuildContext context) =>
-      _createFormatInput(localizations,
-        context,
-        localizations.fieldFormat,
-        localizations.exportFieldFormatDocumentation,
-        recordPattern ?? '',
-        (value) => setState(() {
-          recordPattern = value;
-        }),
-        (value) => (type == _FormatterType.time || value != null && value.isNotEmpty) ? null
-            : localizations.errNoValue,
-      );
+  Column _createRecordFormatInput(
+    AppLocalizations localizations,
+    BuildContext context,
+  ) => _createFormatInput(localizations,
+    context,
+    localizations.fieldFormat,
+    localizations.exportFieldFormatDocumentation,
+    recordPattern ?? '',
+    (value) => setState(() {
+      recordPattern = value;
+    }),
+    (value) => type == _FormatterType.time || value != null && value.isNotEmpty
+        ? null
+        : localizations.errNoValue,
+  );
   
-  Column _createTimeFormatInput(AppLocalizations localizations, BuildContext context) =>
-      _createFormatInput(localizations,
-          context,
-          localizations.timeFormat,
-          localizations.enterTimeFormatDesc,
-          timePattern ?? '',
-          (value) => setState(() {
-            timePattern = value;
-          }),
-          (value) => (type == _FormatterType.record || (value != null && value.isNotEmpty)) ? null
-            : localizations.errNoValue,
-      );
+  Column _createTimeFormatInput(
+    AppLocalizations localizations,
+    BuildContext context,
+  ) => _createFormatInput(localizations,
+    context,
+    localizations.timeFormat,
+    localizations.enterTimeFormatDesc,
+    timePattern ?? '',
+    (value) => setState(() {
+      timePattern = value;
+    }),
+    (value) => (type == _FormatterType.record
+        || (value != null && value.isNotEmpty))
+        ? null
+        : localizations.errNoValue,
+  );
 
   void _saveForm() {
     if (formKey.currentState?.validate() ?? false) {
@@ -239,14 +275,20 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> with Si
       if (type == _FormatterType.record) {
         assert(recordPattern != null, 'validator should check');
         column = (widget.initialColumn != null)
-            ? UserColumn.explicit(widget.initialColumn!.internalIdentifier, csvTitle, recordPattern!)
+            ? 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.explicit(
+              widget.initialColumn!.internalIdentifier,
+              csvTitle,
+              timePattern!,)
             : TimeColumn(csvTitle, timePattern!);
         Navigator.pop(context, column);
       }
@@ -272,7 +314,8 @@ enum _FormatterType {
   time,
 }
 
-/// Shows a dialoge containing a export column editor to create a [UserColumn] or [TimeColumn].
+/// Shows a dialoge containing a export column editor to create a [UserColumn]
+/// or [TimeColumn].
 ///
 /// In case [initialColumn] is null fields are initially empty.
 /// When initialColumn is provided, it is ensured that the
@@ -285,7 +328,15 @@ enum _FormatterType {
 /// Internal identifier and display title are generated from
 /// the CSV title. There is no check whether a userColumn
 /// with the generated title exists.
-Future<ExportColumn?> showAddExportColumnDialoge(BuildContext context, Settings settings, [ExportColumn? initialColumn]) =>
-    showDialog<ExportColumn?>(context: context, builder: (context) => Dialog.fullscreen(
-      child: AddExportColumnDialoge(initialColumn: initialColumn, settings: settings,),
-    ),);
\ No newline at end of file
+Future<ExportColumn?> showAddExportColumnDialoge(
+  BuildContext context,
+  Settings settings, [
+    ExportColumn? initialColumn,
+]) => showDialog<ExportColumn?>(context: context,
+  builder: (context) => Dialog.fullscreen(
+    child: AddExportColumnDialoge(
+      initialColumn: initialColumn,
+      settings: settings,
+    ),
+  ),
+);
lib/components/dialoges/add_measurement_dialoge.dart
@@ -82,7 +82,9 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
     super.initState();
     time = widget.initialRecord?.creationTime ?? DateTime.now();
     needlePin = widget.initialRecord?.needlePin;
-    sysController = TextEditingController(text: (widget.initialRecord?.systolic ?? '').toString());
+    sysController = TextEditingController(
+      text: (widget.initialRecord?.systolic ?? '').toString(),
+    );
 
     sysFocusNode.requestFocus();
     ServicesBinding.instance.keyboard.addHandler(_onKey);
@@ -162,9 +164,11 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
         focusNode: focusNode,
         onSaved: onSaved,
         controller: controller,
-        inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly],
+        inputFormatters: [FilteringTextInputFormatter.digitsOnly],
         onChanged: (String? value) {
-          if (value != null && value.isNotEmpty && (int.tryParse(value) ?? -1) > 40) {
+          if (value != null
+              && value.isNotEmpty
+              && (int.tryParse(value) ?? -1) > 40) {
             FocusScope.of(context).nextFocus();
           }
         },
@@ -174,11 +178,16 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
               medicineId != null && systolic == null && diastolic == null &&
               pulse == null && notes == null && needlePin == null) return null;
 
-          if (!widget.settings.allowMissingValues && (value == null || value.isEmpty || int.tryParse(value) == null)) {
+          if (!widget.settings.allowMissingValues
+              && (value == null
+                  || value.isEmpty
+                  || int.tryParse(value) == null)) {
             return localizations.errNaN;
-          } else if (widget.settings.validateInputs && (int.tryParse(value ?? '') ?? -1) <= 30) {
+          } else if (widget.settings.validateInputs
+              && (int.tryParse(value ?? '') ?? -1) <= 30) {
             return localizations.errLt30;
-          } else if (widget.settings.validateInputs && (int.tryParse(value ?? '') ?? 0) >= 400) {
+          } else if (widget.settings.validateInputs
+              && (int.tryParse(value ?? '') ?? 0) >= 400) {
             // https://pubmed.ncbi.nlm.nih.gov/7741618/
             return localizations.errUnrealistic;
           }
@@ -191,8 +200,10 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
   
 
   /// Build the border all fields have.
-  RoundedRectangleBorder buildShapeBorder([Color? color]) => RoundedRectangleBorder(
-    side: Theme.of(context).inputDecorationTheme.border?.borderSide ?? const BorderSide(width: 3),
+  RoundedRectangleBorder buildShapeBorder([Color? color]) =>
+      RoundedRectangleBorder(
+    side: Theme.of(context).inputDecorationTheme.border?.borderSide
+        ?? const BorderSide(width: 3),
     borderRadius: BorderRadius.circular(20),
   );
 
@@ -204,17 +215,21 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
         if (formKey.currentState?.validate() ?? false) {
           formKey.currentState?.save();
           MedicineIntake? intake;
-          if (_showMedicineDosisInput && medicineDosis != null && medicineId != null) {
+          if (_showMedicineDosisInput
+              && medicineDosis != null
+              && medicineId != null) {
             intake = MedicineIntake(
               timestamp: time,
-              medicine: widget.settings.medications.where((e) => e.id == medicineId).first,
+              medicine: widget.settings.medications
+                  .where((e) => e.id == medicineId).first,
               dosis: medicineDosis!,
             );
           }
           BloodPressureRecord? record;
           if (systolic != null || diastolic != null || pulse != null
               || (notes ?? '').isNotEmpty || needlePin != null) {
-            record = BloodPressureRecord(time, systolic, diastolic, pulse, notes ?? '', needlePin: needlePin);
+            record = BloodPressureRecord(time, systolic, diastolic, pulse,
+              notes ?? '', needlePin: needlePin,);
           }
 
           Navigator.of(context).pop((record, intake));
@@ -379,4 +394,4 @@ Future<(BloodPressureRecord?, MedicineIntake?)?> showAddEntryDialoge(
           initialRecord: initialRecord,
         ),
       ),
-  );
\ No newline at end of file
+  );
lib/components/dialoges/add_medication_dialoge.dart
@@ -6,11 +6,14 @@ import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 
+/// Dialoge to enter values for a [Medicine].
 class AddMedicationDialoge extends StatefulWidget {
+  /// Create a dialoge to enter values for a [Medicine].
   const AddMedicationDialoge({super.key,
     required this.settings,
   });
 
+  /// Settings that determine general behavior.
   final Settings settings;
 
   @override
@@ -102,4 +105,4 @@ class _AddMedicationDialogeState extends State<AddMedicationDialoge> {
 Future<Medicine?> showAddMedicineDialoge(BuildContext context, Settings settings) =>
   showDialog<Medicine?>(context: context, builder: (context) => Dialog.fullscreen(
     child: AddMedicationDialoge(settings: settings),
-  ),);
\ No newline at end of file
+  ),);
lib/components/dialoges/enter_timeformat_dialoge.dart
@@ -22,6 +22,8 @@ class EnterTimeFormatDialoge extends StatefulWidget {
   /// When previewTime is null [DateTime.now] will be used.
   final DateTime? previewTime;
 
+  /// Whether to move the app bar for saving and loading to the bottom of the
+  /// screen.
   final bool bottomAppBars;
 
   @override
@@ -96,4 +98,4 @@ class _EnterTimeFormatDialogeState extends State<EnterTimeFormatDialoge> {
 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/fullscreen_dialoge.dart
@@ -66,4 +66,4 @@ class FullscreenDialoge extends StatelessWidget {
     ],
   );
 
-}
\ No newline at end of file
+}
lib/components/dialoges/input_dialoge.dart
@@ -23,6 +23,7 @@ class InputDialoge extends StatefulWidget {
   /// Optional input validation and formatting overrides.
   final List<TextInputFormatter>? inputFormatters;
 
+  /// The type of keyboard to use for editing the text.
   final TextInputType? keyboardType;
 
   /// Validation function called after submit.
@@ -128,4 +129,4 @@ Future<double?> showNumberInputDialoge(BuildContext context, {String? hintText,
   double? value = double.tryParse(result ?? '');
   value ??= int.tryParse(result ?? '')?.toDouble();
   return value;
-}
\ No newline at end of file
+}
lib/components/measurement_list/intake_list_entry.dart
@@ -54,4 +54,4 @@ class IntakeListEntry extends StatelessWidget {
   );
 
 
-}
\ No newline at end of file
+}
lib/components/measurement_list/measurement_list.dart
@@ -8,13 +8,18 @@ import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 import 'package:provider/provider.dart';
 
+/// List that renders measurements and medicine intakes.
+///
+/// Contains a headline with information about the meaning of "columns".
 class MeasurementList extends StatelessWidget {
+  /// Create a list to display measurements and intakes.
   const MeasurementList({super.key,
     required this.settings,
     required this.records,
     required this.intakes,
   });
 
+  /// Settings that determine general behavior.
   final Settings settings;
 
   /// Records to display.
@@ -110,4 +115,4 @@ class MeasurementList extends StatelessWidget {
       ],
     );
   }
-}
\ No newline at end of file
+}
lib/components/measurement_list/measurement_list_entry.dart
@@ -7,11 +7,15 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 import 'package:intl/intl.dart';
 import 'package:provider/provider.dart';
 
-/// Blood pressure measurement to display in a list.
+/// Display of a blood pressure measurement data.
 class MeasurementListRow extends StatelessWidget {
+  /// Create a display of a measurements.
   const MeasurementListRow({super.key, required this.record, required this.settings});
 
+  /// The measurement to display.
   final BloodPressureRecord record;
+
+  /// Settings that determine general behavior.
   final Settings settings;
 
   @override
@@ -20,7 +24,7 @@ class MeasurementListRow extends StatelessWidget {
     final formatter = DateFormat(settings.dateFormatString);
     return ExpansionTile(
       // Leading color possible
-      title: buildRow(formatter),
+      title: _buildRow(formatter),
       childrenPadding: const EdgeInsets.only(bottom: 10),
       backgroundColor: record.needlePin?.color.withAlpha(30),
       collapsedShape: record.needlePin != null ? Border(left: BorderSide(color: record.needlePin!.color, width: 8)) : null,
@@ -65,7 +69,7 @@ class MeasurementListRow extends StatelessWidget {
     );
   }
 
-  Row buildRow(DateFormat formatter) {
+  Row _buildRow(DateFormat formatter) {
     String formatNum(int? num) => (num ?? '-').toString();
     return Row(
       children: [
@@ -108,7 +112,9 @@ class MeasurementListRow extends StatelessWidget {
   }
 }
 
-Future<bool> showConfirmDeletionDialoge(BuildContext context) async => await showDialog<bool>(context: context,
+/// Show a dialoge that prompts the user to confirm a deletion.
+Future<bool> showConfirmDeletionDialoge(BuildContext context) async =>
+  await showDialog<bool>(context: context,
     builder: (context) => AlertDialog(
       title: Text(AppLocalizations.of(context)!.confirmDelete),
       content: Text(AppLocalizations.of(context)!.confirmDeleteDesc),
lib/components/settings/color_picker_list_tile.dart
@@ -43,4 +43,4 @@ class ColorSelectionListTile extends StatelessWidget {
         if (color != null) onMainColorChanged(color);
       },
     );
-}
\ No newline at end of file
+}
lib/components/settings/dropdown_list_tile.dart
@@ -60,4 +60,4 @@ class _DropDownListTileState<T> extends State<DropDownListTile<T>> {
         onChanged: widget.onChanged,
       ),
     );
-}
\ No newline at end of file
+}
lib/components/settings/input_list_tile.dart
@@ -31,4 +31,4 @@ class InputListTile extends StatelessWidget {
       },
     );
 
-}
\ No newline at end of file
+}
lib/components/settings/number_input_list_tile.dart
@@ -39,4 +39,4 @@ class NumberInputListTile extends StatelessWidget {
         if (result != null) onParsableSubmit(result);
       },
     );
-}
\ No newline at end of file
+}
lib/components/settings/settings_widgets.dart
@@ -6,7 +6,7 @@
 /// List tiles from flutter and this library currently used by the app are:
 /// - [ListTile]
 /// - [SwitchListTile]
-/// - [ColorPickerListTile]
+/// - [ColorSelectionListTile]
 /// - [DropDownListTile]
 /// - [SliderListTile]
 /// - [InputListTile]
lib/components/settings/slider_list_tile.dart
@@ -69,4 +69,4 @@ class SliderListTile extends StatelessWidget {
       ),
     );
 
-}
\ No newline at end of file
+}
lib/components/settings/titled_column.dart
@@ -32,4 +32,4 @@ class TitledColumn extends StatelessWidget {
       children: items,
     );
   }
-}
\ No newline at end of file
+}
lib/components/color_picker.dart
@@ -21,8 +21,8 @@ class ColorPicker extends StatefulWidget {
 
   /// Color that starts out highlighted.
   ///
-  /// When [initialColor] is null the transparent color is selected. When [showTransparentColor] is false as well no
-  /// color is selected.
+  /// When [initialColor] is null the transparent color is selected. When
+  /// [showTransparentColor] is false as well no color is selected.
   final Color? initialColor;
 
   /// Called after a click on a color.
@@ -103,13 +103,18 @@ class _ColorPickerState extends State<ColorPicker> {
               },
               child: Container(
                 decoration: BoxDecoration(
-                  color: _selected == color ? Theme.of(context).disabledColor : Colors.transparent,
+                  color: _selected == color
+                      ? Theme.of(context).disabledColor
+                      : Colors.transparent,
                   shape: BoxShape.circle,),
                 padding: const EdgeInsets.all(5),
                 child: Container(
                   height: widget.circleSize,
                   width: widget.circleSize,
-                  decoration: BoxDecoration(color: color, shape: BoxShape.circle,),
+                  decoration: BoxDecoration(
+                    color: color,
+                    shape: BoxShape.circle,
+                  ),
                 ),
               ),
             ),
@@ -124,7 +129,9 @@ class _ColorPickerState extends State<ColorPicker> {
             child: Container(
               padding: const EdgeInsets.all(5),
               decoration: BoxDecoration(
-                color: _selected == Colors.transparent ? Theme.of(context).disabledColor : Colors.transparent,
+                color: _selected == Colors.transparent
+                    ? Theme.of(context).disabledColor
+                    : Colors.transparent,
                 shape: BoxShape.circle,),
               child: SizedBox(
                 height: widget.circleSize,
@@ -140,21 +147,24 @@ class _ColorPickerState extends State<ColorPicker> {
 /// Shows a dialog with a ColorPicker and with an cancel button inside.
 ///
 /// Returns the selected color or null when cancel is pressed.
-Future<Color?> showColorPickerDialog(BuildContext context, [Color? initialColor]) async => await showDialog(
-    context: context,
-    builder: (_) => AlertDialog(
-        contentPadding: const EdgeInsets.all(6.0),
-        content: ColorPicker(
-          initialColor: initialColor,
-          onColorSelected: (color) {
-            Navigator.of(context).pop(color);
-          },
-        ),
-        actions: [
-          TextButton(
-            onPressed: Navigator.of(context).pop,
-            child: Text(AppLocalizations.of(context)!.btnCancel),
-          ),
-        ],
+Future<Color?> showColorPickerDialog(
+  BuildContext context, [
+    Color? initialColor,
+]) async => showDialog(
+  context: context,
+  builder: (_) => AlertDialog(
+    contentPadding: const EdgeInsets.all(6.0),
+    content: ColorPicker(
+      initialColor: initialColor,
+      onColorSelected: (color) {
+        Navigator.of(context).pop(color);
+      },
+    ),
+    actions: [
+      TextButton(
+        onPressed: Navigator.of(context).pop,
+        child: Text(AppLocalizations.of(context)!.btnCancel),
       ),
-  );
\ No newline at end of file
+    ],
+  ),
+);
lib/components/consistent_future_builder.dart
@@ -1,37 +1,71 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 
+/// A future builder with app defaults.
+///
+/// This allows to have the same loading style everywhere in the app.
 class ConsistentFutureBuilder<T> extends StatefulWidget {
+  /// Create a future builder with app defaults.
+  const ConsistentFutureBuilder({
+    super.key,
+    required this.future,
+    this.onNotStarted,
+    this.onWaiting,
+    this.onError,
+    required this.onData,
+    this.cacheFuture = false,
+    this.lastChildWhileWaiting = false,
+  });
 
-  const ConsistentFutureBuilder({super.key, required this.future, this.onNotStarted, this.onWaiting, this.onError,
-    required this.onData, this.cacheFuture = false, this.lastChildWhileWaiting = false,});
   /// Future that gets evaluated.
   final Future<T> future;
+
+  /// The build strategy once the future loaded.
   final Widget Function(BuildContext context, T result) onData;
-  
+
+  /// The text displayed when no future is connected.
+  ///
+  /// This case should generally be avoided and is protected by assertions in
+  /// debug builds.
+  ///
+  /// Is a 'not started' text by default.
   final Widget? onNotStarted;
+
+  /// The future loading indicator.
+  ///
+  /// Shown while the element is loading. Defaults to 'loading... text'.
   final Widget? onWaiting;
+
+  /// The build strategy in case the future throws an error.
+  ///
+  /// Shows the error message by default.
+  /// FIXME: Currently ignored
   final Widget? Function(BuildContext context, String errorMsg)? onError;
 
   /// Internally save the future and avoid rebuilds.
   ///
-  /// Caching will allow the future builder not to load again in some cases where a rebuild is triggered. But it comes at
-  /// the cost that onData will not be called again, even if data changed.
+  /// Caching will allow the future builder not to load again in some cases
+  /// where a rebuild is triggered. But it comes at the cost that onData will
+  /// not be called again, even if data changed.
   ///
-  /// The parameter is false by default and should only be set to true when rebuilds are disruptive to the user and it
-  /// is certain that the data will not change over the lifetime of the screen.
+  /// The parameter is false by default and should only be set to true when
+  /// rebuilds are disruptive to the user and it is certain that the data will
+  /// not change over the lifetime of the screen.
   final bool cacheFuture;
 
-  /// When loading the next result the child that got build the last time will be returned.
+  /// When loading the next result the child that got build the last time will
+  /// be returned.
   ///
   /// During the first build, [onWaiting] os respected instead.
   final bool lastChildWhileWaiting;
 
   @override
-  State<ConsistentFutureBuilder<T>> createState() => _ConsistentFutureBuilderState<T>();
+  State<ConsistentFutureBuilder<T>> createState() =>
+      _ConsistentFutureBuilderState<T>();
 }
 
-class _ConsistentFutureBuilderState<T> extends State<ConsistentFutureBuilder<T>> {
+class _ConsistentFutureBuilderState<T>
+    extends State<ConsistentFutureBuilder<T>> {
   Future<T>? _future; // avoid rebuilds
   /// Used for returning the last child during load when rebuilding.
   Widget? _lastChild;
@@ -46,21 +80,26 @@ class _ConsistentFutureBuilderState<T> extends State<ConsistentFutureBuilder<T>>
 
   @override
   Widget build(BuildContext context) => FutureBuilder<T>(
-      future: _future ?? widget.future,
-      builder: (BuildContext context, AsyncSnapshot<T> snapshot) {
-        if (snapshot.hasError) {
-          return Text(AppLocalizations.of(context)?.error(snapshot.error.toString()) ?? snapshot.error.toString());
-        }
-        switch (snapshot.connectionState) {
-          case ConnectionState.none:
-            return widget.onNotStarted ?? Text(AppLocalizations.of(context)!.errNotStarted);
-          case ConnectionState.waiting:
-          case ConnectionState.active:
-            if (widget.lastChildWhileWaiting && _lastChild != null) return _lastChild!;
-            return widget.onWaiting ?? Text(AppLocalizations.of(context)!.loading);
-          case ConnectionState.done:
-            _lastChild = widget.onData(context, snapshot.data as T);
+    future: _future ?? widget.future,
+    builder: (BuildContext context, AsyncSnapshot<T> snapshot) {
+      final localizations = AppLocalizations.of(context)!;
+      if (snapshot.hasError) {
+        return Text(localizations.error(snapshot.error.toString()));
+      }
+      switch (snapshot.connectionState) {
+        case ConnectionState.none:
+          assert(false);
+          return widget.onNotStarted ?? Text(localizations.errNotStarted);
+        case ConnectionState.waiting:
+        case ConnectionState.active:
+          if (widget.lastChildWhileWaiting && _lastChild != null) {
             return _lastChild!;
-        }
-      },);
-}
\ No newline at end of file
+          }
+          return widget.onWaiting ?? Text(localizations.loading);
+        case ConnectionState.done:
+          _lastChild = widget.onData(context, snapshot.data as T);
+          return _lastChild!;
+      }
+    },
+  );
+}
lib/components/custom_banner.dart
@@ -47,5 +47,4 @@ class CustomBanner extends StatelessWidget {
       ],
     ),
   );
-
-}
\ No newline at end of file
+}
lib/components/date_time_picker.dart
@@ -1,11 +1,13 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 
-/// First shows a DatePicker for the day then shows a TimePicker for the time of day.
+/// First shows a DatePicker for the day then shows a TimePicker for the time of
+/// day.
 ///
-/// As per the decision of the material design team a TimePicker isn't able to limit the range
-/// (https://github.com/flutter/flutter/issues/23717#issuecomment-966601311), therefore a manual check for the time of
-/// day will be needed. Refer to the validator on the AddMeasurementPage for an example
+/// As per the decision of the material design team a TimePicker isn't able to
+/// limit the range (https://github.com/flutter/flutter/issues/23717#issuecomment-966601311),
+/// therefore a manual check for the time of day will be needed. Refer to the
+/// validator on the AddMeasurementPage for an example.
 Future<DateTime?> showDateTimePicker({
   required BuildContext context,
   DateTime? initialDate,
@@ -17,7 +19,12 @@ Future<DateTime?> showDateTimePicker({
   lastDate ??= firstDate.add(const Duration(days: 365 * 200));
 
   final DateTime? selectedDate = await showDatePicker(
-      context: context, initialDate: initialDate, firstDate: firstDate, lastDate: lastDate, confirmText: AppLocalizations.of(context)!.btnNext,);
+    context: context,
+    initialDate: initialDate,
+    firstDate: firstDate,
+    lastDate: lastDate,
+    confirmText: AppLocalizations.of(context)!.btnNext,
+  );
 
   if (selectedDate == null) return null;
   if (!context.mounted) return null;
lib/components/disabled.dart
@@ -1,17 +1,22 @@
 
 import 'package:flutter/material.dart';
 
-/// A widget that visually indicates that it's subtree is disabled and blocks all interaction with it.
+/// A widget that visually indicates that it's subtree is disabled and blocks
+/// all interaction with it.
 class Disabled extends StatelessWidget {
-  /// Create a widget that visually indicates that it's subtree is disabled and blocks interaction with it.
+  /// Create a widget that visually indicates that it's subtree is disabled
+  /// and blocks interaction with it.
   ///
-  /// If [disabled] is true the [child]s opacity gets reduced and interaction gets disabled. This widget has no effect
-  /// when [disabled] is false.
+  /// If [disabled] is true the [child]s opacity gets reduced and interaction
+  /// gets disabled. This widget has no effect when [disabled] is false.
   const Disabled({required this.child, this.disabled = true, this.ignoring = true, super.key});
 
+  /// The widget to render as disabled.
   final Widget child;
+
   /// Whether this widget has an effect.
   final bool disabled;
+
   /// Whether interaction is blocked.
   final bool ignoring;
 
@@ -29,4 +34,4 @@ class Disabled extends StatelessWidget {
     return child;
   }
 
-}
\ No newline at end of file
+}
lib/components/export_warn_banner.dart
@@ -11,7 +11,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 
 /// Banner that gives the user information on the importability of their export.
 class ExportWarnBanner extends StatefulWidget {
-  /// Create either a banner that informs the user of import problems or an empty widget.
+  /// Create either a banner that informs the user of import problems or an
+  /// empty widget.
   ///
   /// Whether the config is importable is determined by the passed settings.
   const ExportWarnBanner({super.key,
@@ -19,8 +20,14 @@ class ExportWarnBanner extends StatefulWidget {
     required this.csvExportSettings,
     required this.availableColumns,});
 
+  /// The [ExportSettings] validated for importability.
   final ExportSettings exportSettings;
+
+  /// The [CsvExportSettings] validated for importability if applicable.
   final CsvExportSettings csvExportSettings;
+
+  /// The columns used to validate importability in case custom export is
+  /// enabled.
   final ExportColumnsManager availableColumns;
 
   @override
@@ -118,4 +125,4 @@ class _ExportWarnBannerState extends State<ExportWarnBanner> {
         child: Text(localizations.btnConfirm),
       ),
     );
-}
\ No newline at end of file
+}
lib/model/blood_pressure/medicine/intake_history.dart
@@ -137,4 +137,4 @@ class IntakeHistory extends ChangeNotifier {
 
   @override
   int get hashCode => _medicineIntakes.hashCode;
-}
\ No newline at end of file
+}
lib/model/blood_pressure/medicine/medicine.dart
@@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
 
 /// Description of a specific medicine.
 class Medicine {
-
+  /// Create a instance from a map created by [toMap].
   factory Medicine.fromMap(Map<String, dynamic> map) => Medicine(
     map['id'],
     designation: map['designation'],
@@ -14,7 +14,9 @@ class Medicine {
     defaultDosis: map['defaultDosis'],
   );
 
+  /// Create a instance from a [String] created by [toJson].
   factory Medicine.fromJson(String json) => Medicine.fromMap(jsonDecode(json));
+
   /// Create a new medicine.
   const Medicine(this.id, {
     required this.designation,
@@ -22,6 +24,7 @@ class Medicine {
     required this.defaultDosis,
   });
 
+  /// Serialize the object to a restoreable map.
   Map<String, dynamic> toMap() => {
     'id': id,
     'designation': designation,
@@ -29,6 +32,7 @@ class Medicine {
     'defaultDosis': defaultDosis,
   };
 
+  /// Serialize the object to a restoreable string.
   String toJson() => jsonEncode(toMap());
 
   /// Unique id used to store the medicine in serialized objects.
lib/model/blood_pressure/medicine/medicine_intake.dart
@@ -3,7 +3,7 @@ import 'package:blood_pressure_app/model/blood_pressure/medicine/medicine.dart';
 
 /// Instance of a medicine intake.
 class MedicineIntake implements Comparable<Object> {
-
+  /// Create a intake from a String created by [serialize].
   factory MedicineIntake.deserialize(String string, List<Medicine> availableMeds) {
     final elements = string.split('\x00');
     return MedicineIntake(
@@ -12,6 +12,7 @@ class MedicineIntake implements Comparable<Object> {
       dosis: double.parse(elements[2]),
     );
   }
+
   /// Create a instance of a medicine intake.
   const MedicineIntake({
     required this.medicine,
@@ -60,4 +61,4 @@ class MedicineIntake implements Comparable<Object> {
 
   @override
   String toString() => 'MedicineIntake{medicine: $medicine, dosis: $dosis, timestamp: $timestamp}';
-}
\ No newline at end of file
+}
lib/model/blood_pressure/model.dart
@@ -12,10 +12,13 @@ import 'package:path/path.dart';
 import 'package:provider/provider.dart';
 import 'package:sqflite/sqflite.dart';
 
+/// Model to access values in the measurement database.
 class BloodPressureModel extends ChangeNotifier {
 
   BloodPressureModel._create();
+
   late final Database _database;
+
   Future<void> _asyncInit(String? dbPath, bool isFullPath) async {
     dbPath ??= await getDatabasesPath();
 
@@ -117,6 +120,10 @@ class BloodPressureModel extends ChangeNotifier {
     }
   }
 
+  /// Try to remove the measurement at a specific timestamp from the database.
+  ///
+  /// When no measurement at that time exists, the operation won't fail and
+  /// listeners will get notified anyways.
   Future<void> delete(DateTime timestamp) async {
     if (!_database.isOpen) return;
     _database.delete('bloodPressureModel', where: 'timestamp = ?', whereArgs: [timestamp.millisecondsSinceEpoch]);
@@ -134,11 +141,15 @@ class BloodPressureModel extends ChangeNotifier {
     return UnmodifiableListView(recordsInRange);
   }
 
+  /// Querries all measurements saved in the database.
   Future<UnmodifiableListView<BloodPressureRecord>> get all async {
     if (!_database.isOpen) return UnmodifiableListView([]);
     return UnmodifiableListView(_convert(await _database.query('bloodPressureModel', columns: ['*'])));
   }
 
+  /// Close the database.
+  ///
+  /// Cannot be accessed anymore.
   Future<void> close() => _database.close();
 
   List<BloodPressureRecord> _convert(List<Map<String, Object?>> dbResult) {
@@ -158,4 +169,3 @@ class BloodPressureModel extends ChangeNotifier {
     return records;
   }
 }
-
lib/model/blood_pressure/needle_pin.dart
@@ -1,17 +1,26 @@
+import 'package:blood_pressure_app/model/blood_pressure/record.dart';
 import 'package:flutter/material.dart';
 
 @immutable
+/// Metadata and secondary information for a [BloodPressureRecord].
 class MeasurementNeedlePin {
-
+  /// Create metadata for a [BloodPressureRecord].
   const MeasurementNeedlePin(this.color);
-  // When updating this, remember to be backwards compatible
+
+  /// Create a instance from a map created by [toMap].
   MeasurementNeedlePin.fromJson(Map<String, dynamic> json)
       : color = Color(json['color']);
+  // When updating this, remember to be backwards compatible.
+  // (or reimplement the system)
+
+  /// The color associated with the measurement.
   final Color color;
-  Map<String, dynamic> toJson() => {
+
+  /// Serialize the object to a restoreable map.
+  Map<String, dynamic> toMap() => {
     'color': color.value,
   };
 
   @override
   String toString() => 'MeasurementNeedlePin{$color}';
-}
\ No newline at end of file
+}
lib/model/blood_pressure/record.dart
@@ -2,8 +2,9 @@ import 'package:blood_pressure_app/model/blood_pressure/needle_pin.dart';
 import 'package:flutter/material.dart';
 
 @immutable
+/// Immutable data representation of a saved measurement.
 class BloodPressureRecord {
-
+  /// Create a measurement.
   BloodPressureRecord(DateTime creationTime, this.systolic, this.diastolic, this.pulse, this.notes, {
     this.needlePin,
   }) {
@@ -14,13 +15,25 @@ class BloodPressureRecord {
       this.creationTime = DateTime.fromMillisecondsSinceEpoch(1);
     }
   }
+
+  /// The time the measurement was created.
   late final DateTime creationTime;
+
+  /// The stored sys value.
   final int? systolic;
+
+  /// The stored dia value.
   final int? diastolic;
+
+  /// The stored pul value.
   final int? pulse;
+
+  /// Notes stored about this measurement.
   final String notes;
+
+  /// Secondary information about the measurement.
   final MeasurementNeedlePin? needlePin;
 
   @override
   String toString() => 'BloodPressureRecord($creationTime, $systolic, $diastolic, $pulse, $notes, $needlePin)';
-}
\ No newline at end of file
+}
lib/model/blood_pressure/warn_values.dart
@@ -1,9 +1,13 @@
-// source: https://pressbooks.library.torontomu.ca/vitalsign/chapter/blood-pressure-ranges/ (last access: 14.11.2023)
+/// Static provider of warn values for ages.
+///
+/// source: https://pressbooks.library.torontomu.ca/vitalsign/chapter/blood-pressure-ranges/ (last access: 14.11.2023)
 class BloodPressureWarnValues {
   BloodPressureWarnValues._create();
 
+  /// URL from which the information was taken.
   static String source = 'https://pressbooks.library.torontomu.ca/vitalsign/chapter/blood-pressure-ranges/';
 
+  /// Returns the default highest (safe) diastolic value for a specific age.
   static int getUpperDiaWarnValue(int age) {
     if (age <= 2) {
       return 70;
@@ -20,6 +24,7 @@ class BloodPressureWarnValues {
     }
   }
 
+  /// Returns the default highest (safe) systolic value for a specific age.
   static int getUpperSysWarnValue(int age) {
     if (age <= 2) {
       return 100;
@@ -35,4 +40,4 @@ class BloodPressureWarnValues {
       return 145;
     }
   }
-}
\ No newline at end of file
+}
lib/model/export_import/column.dart
@@ -2,6 +2,7 @@ import 'dart:convert';
 
 import 'package:blood_pressure_app/model/blood_pressure/needle_pin.dart';
 import 'package:blood_pressure_app/model/blood_pressure/record.dart';
+import 'package:blood_pressure_app/model/export_import/export_configuration.dart';
 import 'package:blood_pressure_app/model/export_import/import_field_type.dart';
 import 'package:blood_pressure_app/model/export_import/record_formatter.dart';
 import 'package:flutter/material.dart';
@@ -69,7 +70,7 @@ class NativeColumn extends ExportColumn {
     static final NativeColumn needlePin = NativeColumn._create(
       'needlePin',
       RowDataFieldType.needlePin,
-      (record) => jsonEncode(record.needlePin?.toJson()),
+      (record) => jsonEncode(record.needlePin?.toMap()),
       (pattern) {
         final json = jsonDecode(pattern);
         if (json is! Map<String, dynamic>) return null;
@@ -267,6 +268,8 @@ class UserColumn extends ExportColumn {
   RowDataFieldType? get restoreAbleType => formatter.restoreAbleType;
 }
 
+/// A measurement formatters that converts the timestamp to a string using ICU
+/// patterns.
 class TimeColumn extends ExportColumn {
   /// Create a formatter that converts between [String]s and [DateTime]s
   /// through a format pattern.
lib/model/export_import/export_configuration.dart
@@ -19,6 +19,7 @@ class ActiveExportColumnConfiguration extends ChangeNotifier {
       _activePreset = activePreset ?? ExportImportPreset.bloodPressureApp,
       _userSelectedColumns = userSelectedColumnIds ?? [];
 
+  /// Create a instance from a [String] created by [toJson].
   factory ActiveExportColumnConfiguration.fromJson(String jsonString) {
     try {
       final json = jsonDecode(jsonString);
@@ -32,6 +33,7 @@ class ActiveExportColumnConfiguration extends ChangeNotifier {
 
   }
 
+  /// Serialize the object to a restoreable string.
   String toJson() => jsonEncode({
     'columns': _userSelectedColumns,
     'preset': _activePreset.encode(),
@@ -43,7 +45,10 @@ class ActiveExportColumnConfiguration extends ChangeNotifier {
   final List<String> _userSelectedColumns;
 
   ExportImportPreset _activePreset;
+
+  /// The current selection on what set of values will be exported.
   ExportImportPreset get activePreset => _activePreset;
+
   set activePreset(ExportImportPreset value) {
     _activePreset = value;
     notifyListeners();
@@ -124,8 +129,10 @@ enum ExportImportPreset {
   /// Includes formatted time, sys, dia and pulse.
   bloodPressureAppPdf,
 
+  /// Preset for exporting data to the myHeart app.
   myHeart;
 
+  /// Selection of a displayable string from [localizations].
   String localize(AppLocalizations localizations) => switch (this) {
     ExportImportPreset.none => localizations.custom,
     ExportImportPreset.bloodPressureApp => localizations.default_,
@@ -133,6 +140,7 @@ enum ExportImportPreset {
     ExportImportPreset.myHeart => '"My Heart" export'
   };
 
+  /// Turn the value into a [decode]able integer for serialization purposes.
   int encode() => switch (this) {
     ExportImportPreset.none => 0,
     ExportImportPreset.bloodPressureApp => 1,
@@ -140,7 +148,8 @@ enum ExportImportPreset {
     ExportImportPreset.bloodPressureAppPdf => 3,
   };
 
-  static ExportImportPreset? decode(e) => switch(e) {
+  /// Create a enum value form a number returned by [encode].
+  static ExportImportPreset? decode(Object? e) => switch(e) {
       0 => ExportImportPreset.none,
       1 => ExportImportPreset.bloodPressureApp,
       2 => ExportImportPreset.myHeart,
@@ -150,4 +159,4 @@ enum ExportImportPreset {
         return null;
       }(),
     };
-}
\ No newline at end of file
+}
lib/model/export_import/import_field_type.dart
@@ -4,8 +4,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 
 
 /// Type a [Formatter] can uses to indicate the kind of data returned.
-///
-/// The data types returned from the deprecated [LegacyExportColumn] may differ from the guarantees.
 enum RowDataFieldType {
   /// Guarantees [DateTime] is returned.
   timestamp,
@@ -20,6 +18,7 @@ enum RowDataFieldType {
   /// Guarantees that the returned type is of type [MeasurementNeedlePin].
   needlePin;
 
+  /// Selection of a displayable string from [localizations].
   String localize(AppLocalizations localizations) {
     switch(this) {
       case RowDataFieldType.timestamp:
@@ -36,4 +35,4 @@ enum RowDataFieldType {
         return localizations.color;
     }
   }
-}
\ No newline at end of file
+}
lib/model/export_import/pdf_converter.dart
@@ -57,7 +57,7 @@ class PdfConverter {
       },
       maxPages: 100,
     ),);
-    return await pdf.save();
+    return pdf.save();
   }
 
   pw.Widget _buildPdfTitle(List<BloodPressureRecord> records, BloodPressureAnalyser analyzer) {
@@ -191,8 +191,6 @@ class PdfConverter {
 
         int rowCount = (availableHeightOnFirstPage - realHeaderHeight)
             ~/ (realCellHeight);
-        
-        print(rowCount);
 
         final List<pw.Widget> tables = [];
         int pageNum = 0;
@@ -263,6 +261,6 @@ class PdfConverter {
   }
 }
 
-extension PdfCompatability on Color {
+extension _PdfCompatability on Color {
   PdfColor toPdfColor() => PdfColor(red / 256, green / 256, blue / 256, opacity);
-}
\ No newline at end of file
+}
lib/model/export_import/record_formatter.dart
@@ -9,7 +9,7 @@ import 'package:intl/intl.dart';
 
 /// Class to serialize and deserialize [BloodPressureRecord] values.
 abstract interface class Formatter {
-  /// Pattern that a user can use to achieve the effect of [convertToCsvValue].
+  /// Pattern that a user can use to achieve the effect of [encode].
   String? get formatPattern;
 
   /// Creates a string representation of the record.
@@ -31,8 +31,9 @@ abstract interface class Formatter {
   (RowDataFieldType, dynamic)? decode(String pattern);
 }
 
-/// Record [Formatter] that is based on a format pattern.
+/// Measurement [Formatter] that is based on a format pattern.
 class ScriptedFormatter implements Formatter {
+  /// Create a [BloodPressureRecord] formatter from a format pattern.
   ScriptedFormatter(this.pattern);
 
   /// Pattern used for formatting values.
@@ -79,7 +80,7 @@ class ScriptedFormatter implements Formatter {
     fieldContents = fieldContents.replaceAll(r'$DIA', record.diastolic.toString());
     fieldContents = fieldContents.replaceAll(r'$PUL', record.pulse.toString());
     fieldContents = fieldContents.replaceAll(r'$NOTE', record.notes);
-    fieldContents = fieldContents.replaceAll(r'$COLOR', jsonEncode(record.needlePin?.toJson()));
+    fieldContents = fieldContents.replaceAll(r'$COLOR', jsonEncode(record.needlePin?.toMap()));
 
     // math
     fieldContents = fieldContents.replaceAllMapped(RegExp(r'\{\{([^}]*)}}'), (m) {
@@ -177,26 +178,26 @@ class ScriptedTimeFormatter implements Formatter {
   ///
   /// The pattern follows the ICU style like [DateFormat].
   ScriptedTimeFormatter(String newPattern):
-    timeFormatter = DateFormat(newPattern);
+    _timeFormatter = DateFormat(newPattern);
 
-  final DateFormat timeFormatter;
+  final DateFormat _timeFormatter;
   
   @override
   (RowDataFieldType, dynamic)? decode(String pattern) {
     if (pattern.isEmpty) return null;
     try {
-      return (RowDataFieldType.timestamp, timeFormatter.parseLoose(pattern));
+      return (RowDataFieldType.timestamp, _timeFormatter.parseLoose(pattern));
     } on FormatException {
       return null;
     }
   }
 
   @override
-  String encode(BloodPressureRecord record) => timeFormatter.format(record.creationTime);
+  String encode(BloodPressureRecord record) => _timeFormatter.format(record.creationTime);
 
   @override
-  String? get formatPattern => timeFormatter.pattern;
+  String? get formatPattern => _timeFormatter.pattern;
 
   @override
   RowDataFieldType? get restoreAbleType => RowDataFieldType.timestamp;
-}
\ No newline at end of file
+}
lib/model/export_import/record_parsing_result.dart
@@ -68,4 +68,4 @@ class RecordParsingErrorUnparsableField implements RecordParsingError {
   
   /// Text in the csv string that failed to parse.
   final String fieldContents;
-}
\ No newline at end of file
+}
lib/model/storage/db/config_dao.dart
@@ -9,12 +9,15 @@ import 'package:sqflite/sqflite.dart';
 
 /// Class for loading data from the database.
 ///
-/// The user of this class needs to pay attention to dispose all old instances of objects created by the instance
-/// methods in order to ensure there are no concurrent writes to the database. Having multiple instances will cause data
+/// The user of this class needs to pay attention to dispose all old instances
+/// of objects created by the instance methods in order to ensure there are no
+/// concurrent writes to the database. Having multiple instances will cause data
 /// loss because states are not synced again after one changes.
 ///
-/// The load... methods have to schedule a initial save to db in case an migration / update of fields occurred.
+/// The load... methods have to schedule a initial save to db in case an
+/// migration / update of fields occurred.
 class ConfigDao {
+  /// Create a serializer to initialize data from a database.
   ConfigDao(this._configDB);
 
   final ConfigDB _configDB;
@@ -22,8 +25,9 @@ class ConfigDao {
   final Map<int, Settings> _settingsInstances = {};
   /// Loads the profiles [Settings] object from the database.
   ///
-  /// If any errors occur or the object is not present, a default one will be created. Changes in the object
-  /// will save to the database automatically (a listener gets attached).
+  /// If any errors occur or the object is not present, a default one will be
+  /// created. Changes in the object will save to the database automatically (a
+  /// listener gets attached).
   ///
   /// Changes to the database will not propagate to the object.
   Future<Settings> loadSettings(int profileID) async {
@@ -330,4 +334,4 @@ class ConfigDao {
         conflictAlgorithm: ConflictAlgorithm.replace,
     );
   }
-}
\ No newline at end of file
+}
lib/model/storage/db/config_db.dart
@@ -72,7 +72,7 @@ class ConfigDB {
       'INTEGER, storage_id INTEGER, stepSize INTEGER, start INTEGER, end INTEGER, '
       'PRIMARY KEY(profile_id, storage_id))';
 
-  /// Name of the exportStrings table. It is used to store formats used in the [ExportConfigurationModel].
+  /// Name of the exportStrings table. It is used to to update old columns.
   ///
   /// Format:
   /// `CREATE TABLE exportStrings(internalColumnName STRING PRIMARY KEY, columnTitle STRING, formatPattern STRING)`
lib/model/storage/common_settings_interfaces.dart
@@ -8,4 +8,4 @@ abstract class CustomFieldsSettings {
   ///
   /// Implementers must propagate any notifyListener calls.
   ActiveExportColumnConfiguration get exportFieldsConfiguration;
-}
\ No newline at end of file
+}
lib/model/storage/convert_util.dart
@@ -90,7 +90,8 @@ class ConvertUtil {
     return null;
   }
 
-  static ThemeMode? parseThemeMode(value) {
+  /// Try to recreate the theme mode stored as a integer.
+  static ThemeMode? parseThemeMode(dynamic value) {
     final int? intValue = ConvertUtil.parseInt(value);
     switch(intValue) {
       case null:
@@ -106,4 +107,4 @@ class ConvertUtil {
         return null;
     }
   }
-}
\ No newline at end of file
+}
lib/model/storage/export_columns_store.dart
@@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
 
 /// Class for managing columns available to the user.
 class ExportColumnsManager extends ChangeNotifier {
-
+  /// Create a instance from a map created by [toMap].
   factory ExportColumnsManager.fromMap(Map<String, dynamic> map) {
     final List<dynamic> jsonUserColumns = map['userColumns'];
     final manager = ExportColumnsManager();
@@ -25,6 +25,7 @@ class ExportColumnsManager extends ChangeNotifier {
     return manager;
   }
 
+  /// Create a instance from a [String] created by [toJson].
   factory ExportColumnsManager.fromJson(String jsonString) {
     try {
       return ExportColumnsManager.fromMap(jsonDecode(jsonString));
@@ -38,15 +39,19 @@ class ExportColumnsManager extends ChangeNotifier {
   /// It will be filled with the default columns but won't contain initial user columns.
   ExportColumnsManager();
 
+  /// Namespaces that may not lead a user columns internal identifier.
   static const List<String> reservedNamespaces = ['buildIn', 'myHeart'];
 
-  /// Map between all [ExportColumn.internalIdentifier]s and [ExportColumn]s added by a user.
+  /// Map between all [ExportColumn.internalIdentifier]s and [ExportColumn]s
+  /// added by a user.
   final Map<String, ExportColumn> _userColumns = {};
 
-  /// View of map between all [ExportColumn.internalName]s and [ExportColumn]s added by a user.
+  /// View of map between all [ExportColumn.internalIdentifier]s and columns
+  /// added by a user.
   UnmodifiableMapView<String, ExportColumn> get userColumns => UnmodifiableMapView(_userColumns);
 
-  /// Tries to save the column to the map with the [ExportColumn.internalName] key.
+  /// Tries to save the column to the map with the [ExportColumn.internalIdentifier]
+  /// key.
   ///
   /// This method fails and returns false when there is a default [ExportColumn] with the same internal name is
   /// available.
@@ -77,12 +82,11 @@ class ExportColumnsManager extends ChangeNotifier {
   /// 1. userColumns 
   /// 2. NativeColumn 
   /// 3. BuildInColumn
-  ExportColumn? firstWhere(bool Function(ExportColumn) test) {
-    return userColumns.values.where(test).firstOrNull
-        ?? NativeColumn.allColumns.where(test).firstOrNull
-        ?? BuildInColumn.allColumns.where(test).firstOrNull; 
-        // ?? ...
-  }
+  ExportColumn? firstWhere(bool Function(ExportColumn) test) =>
+    userColumns.values.where(test).firstOrNull
+      ?? NativeColumn.allColumns.where(test).firstOrNull
+      ?? BuildInColumn.allColumns.where(test).firstOrNull;
+      // ?? ...
 
   /// Returns a list of all userColumns, NativeColumns and BuildInColumns defined.
   ///
@@ -103,6 +107,7 @@ class ExportColumnsManager extends ChangeNotifier {
     return UnmodifiableListView(columns);
   }
 
+  /// Serialize the object to a restoreable map.
   Map<String, dynamic> toMap() {
     final columns = [];
     for (final c in _userColumns.values) {
@@ -134,6 +139,7 @@ class ExportColumnsManager extends ChangeNotifier {
     };
   }
 
+  /// Serialize the object to a restoreable string.
   String toJson() => jsonEncode(toMap());
 }
 
lib/model/storage/intervall_store.dart
@@ -7,12 +7,13 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 
 /// Class for storing the current interval, as it is needed in start page, statistics and export.
 class IntervallStorage extends ChangeNotifier {
-
+  /// Create a instance from a map created by [toMap].
   factory IntervallStorage.fromMap(Map<String, dynamic> map) => IntervallStorage(
     stepSize: TimeStep.deserialize(map['stepSize']),
     range: ConvertUtil.parseRange(map['start'], map['end']),
   );
 
+  /// Create a instance from a [String] created by [toJson].
   factory IntervallStorage.fromJson(String json) {
     try {
       return IntervallStorage.fromMap(jsonDecode(json));
@@ -20,19 +21,25 @@ class IntervallStorage extends ChangeNotifier {
       return IntervallStorage();
     }
   }
-  IntervallStorage({TimeStep? stepSize, DateTimeRange? range}) {
-    _stepSize = stepSize ?? TimeStep.last7Days;
+
+  /// Create a storage to interact with a display intervall.
+  IntervallStorage({TimeStep? stepSize, DateTimeRange? range}) :
+    _stepSize = stepSize ?? TimeStep.last7Days {
     _currentRange = range ?? _getMostRecentDisplayIntervall();
   }
-  late TimeStep _stepSize;
+
+  TimeStep _stepSize;
+
   late DateTimeRange _currentRange;
 
+  /// Serialize the object to a restoreable map.
   Map<String, dynamic> toMap() => <String, dynamic>{
     'stepSize': stepSize.serialize(),
     'start': currentRange.start.millisecondsSinceEpoch,
     'end': currentRange.end.millisecondsSinceEpoch,
   };
 
+  /// Serialize the object to a restoreable string.
   String toJson() => jsonEncode(toMap());
 
   /// The stepSize gets set through the changeStepSize method.
@@ -155,6 +162,34 @@ enum TimeStep {
   last30Days,
   custom;
 
+  /// Recreate a TimeStep from a number created with [TimeStep.serialize].
+  factory TimeStep.deserialize(value) {
+    final int? intValue = ConvertUtil.parseInt(value);
+    if (intValue == null) return TimeStep.last7Days;
+
+    switch (intValue) {
+      case 0:
+        return TimeStep.day;
+      case 1:
+        return TimeStep.month;
+      case 2:
+        return TimeStep.year;
+      case 3:
+        return TimeStep.lifetime;
+      case 4:
+        return TimeStep.week;
+      case 5:
+        return TimeStep.last7Days;
+      case 6:
+        return TimeStep.last30Days;
+      case 7:
+        return TimeStep.custom;
+      default:
+        assert(false);
+        return TimeStep.last7Days;
+    }
+  }
+
   static const options = [TimeStep.day, TimeStep.week, TimeStep.month, TimeStep.year, TimeStep.lifetime, TimeStep.last7Days, TimeStep.last30Days, TimeStep.custom];
 
   String getName(AppLocalizations localizations) {
@@ -198,33 +233,6 @@ enum TimeStep {
         return 7;
     }
   }
-
-  factory TimeStep.deserialize(value) {
-    final int? intValue = ConvertUtil.parseInt(value);
-    if (intValue == null) return TimeStep.last7Days;
-
-    switch (intValue) {
-      case 0:
-        return TimeStep.day;
-      case 1:
-        return TimeStep.month;
-      case 2:
-        return TimeStep.year;
-      case 3:
-        return TimeStep.lifetime;
-      case 4:
-        return TimeStep.week;
-      case 5:
-        return TimeStep.last7Days;
-      case 6:
-        return TimeStep.last30Days;
-      case 7:
-        return TimeStep.custom;
-      default:
-        assert(false);
-        return TimeStep.last7Days;
-    }
-  }
 }
 
 /// Class that stores the interval objects that are needed in the app and provides named access to them. 
lib/model/storage/storage.dart
@@ -22,4 +22,4 @@ export 'export_pdf_settings_store.dart';
 export 'export_settings_store.dart';
 export 'intervall_store.dart';
 export 'settings_store.dart';
-export 'update_legacy_settings.dart';
\ No newline at end of file
+export 'update_legacy_settings.dart';
lib/model/storage/update_legacy_settings.dart
@@ -224,4 +224,4 @@ Future<void> updateLegacyExport(ConfigDB database, ExportColumnsManager manager)
 }
 
 Future<bool> _tableExists(Database database, String tableName) async => (await database.rawQuery(
-  "SELECT name FROM sqlite_master WHERE type='table' AND name='$tableName';",)).isNotEmpty;
\ No newline at end of file
+  "SELECT name FROM sqlite_master WHERE type='table' AND name='$tableName';",)).isNotEmpty;
lib/model/blood_pressure_analyzer.dart
@@ -3,37 +3,51 @@ import 'dart:math';
 import 'package:blood_pressure_app/model/blood_pressure/record.dart';
 import 'package:collection/collection.dart';
 
+/// Analysis utils for a list of blood pressure records.
 class BloodPressureAnalyser {
-
+  /// Create a analyzer for a list of records.
   BloodPressureAnalyser(this._records);
+
   final List<BloodPressureRecord> _records;
 
+  /// The amount of records saved.
   int get count => _records.length;
 
+  /// The average diastolic values of all records.
   int get avgDia => _safeResult(() => _nonNullDia.average.toInt(), (r) => r.diastolic);
 
+  /// The average pulse values of all records.
   int get avgPul => _safeResult(() => _nonNullPul.average.toInt(), (r) => r.pulse);
 
+  /// The average systolic values of all records.
   int get avgSys => _safeResult(() => _nonNullSys.average.toInt(), (r) => r.systolic);
 
+  /// The maximum diastolic values of all records.
   int get maxDia => _safeResult(() => _nonNullDia.reduce(max), (r) => r.diastolic);
 
+  /// The maximum pulse values of all records.
   int get maxPul => _safeResult(() => _nonNullPul.reduce(max), (r) => r.pulse);
 
+  /// The maximum systolic values of all records.
   int get maxSys => _safeResult(() => _nonNullSys.reduce(max), (r) => r.systolic);
 
+  /// The minimal diastolic values of all records.
   int get minDia => _safeResult(() => _nonNullDia.reduce(min), (r) => r.diastolic);
 
+  /// The minimal pulse values of all records.
   int get minPul => _safeResult(() =>  _nonNullPul.reduce(min), (r) => r.pulse);
 
+  /// The minimal systolic values of all records.
   int get minSys => _safeResult(() => _nonNullSys.reduce(min), (r) => r.systolic);
 
+  /// The earliest timestamp of all records.
   DateTime? get firstDay {
     if (_records.isEmpty) return null;
     _records.sort((a, b) => a.creationTime.compareTo(b.creationTime));
     return _records.first.creationTime;
   }
 
+  /// The latest timestamp of all records.
   DateTime? get lastDay {
     if (_records.isEmpty) return null;
     _records.sort((a, b) => a.creationTime.compareTo(b.creationTime));
@@ -54,6 +68,7 @@ class BloodPressureAnalyser {
   Iterable<int> get _nonNullSys => _records.map((e) => e.systolic).whereNotNull();
   Iterable<int> get _nonNullPul => _records.map((e) => e.pulse).whereNotNull();
 
+  /// Average amount of measurements entered per day.
   int get measurementsPerDay {
     final c = count;
     if (c <= 1) return -1;
@@ -72,6 +87,8 @@ class BloodPressureAnalyser {
     return c ~/ lastDay.difference(firstDay).inDays;
   }
 
+  /// Relation of average values to the time of the day.
+  ///
   /// outer list is type (0 -> diastolic, 1 -> systolic, 2 -> pulse)
   /// inner list index is hour of day ([0] -> 00:00-00:59; [1] -> ...)
   List<List<int>> get allAvgsRelativeToDaytime {
lib/model/horizontal_graph_line.dart
@@ -1,11 +1,17 @@
 import 'package:blood_pressure_app/model/blood_pressure/record.dart';
 import 'package:flutter/material.dart';
 
+/// Information about a straight horizontal line through the graph.
+///
+/// Can be used to indicate value ranges and provide a frame of reference to the
+/// user.
 class HorizontalGraphLine {
-
+  /// Create a instance from a [String] created by [toJson].
   HorizontalGraphLine.fromJson(Map<String, dynamic> json)
       : color = Color(json['color']),
         height = json['height'];
+
+  /// Create information about a new horizontal line through the graph.
   HorizontalGraphLine(this.color, this.height);
 
   /// Color of the line.
@@ -16,8 +22,9 @@ class HorizontalGraphLine {
   /// Usually on the same scale as [BloodPressureRecord]
   int height;
 
+  /// Serialize the object to a restoreable string.
   Map<String, dynamic> toJson() => {
     'color': color.value,
     'height': height,
   };
-}
\ No newline at end of file
+}
lib/model/iso_lang_names.dart
@@ -185,4 +185,7 @@ final _isoLangs = {
   'za': 'Saɯ cueŋƅ, Saw cuengh',
 };
 
+/// Selects the correct language name for a specific language code.
+///
+/// Does not account for dialects.
 String? getDisplayLanguage(Locale l) => _isoLangs[l.languageCode];
lib/platform_integration/platform_client.dart
@@ -65,4 +65,4 @@ class PlatformClient {
       return false;
     }
   }
-}
\ No newline at end of file
+}
lib/screens/elements/blood_pressure_builder.dart
@@ -7,11 +7,19 @@ import 'package:blood_pressure_app/model/storage/intervall_store.dart';
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 
-/// Shorthand class for getting the blood pressure values
+/// Shorthand class for getting the blood pressure values.
 class BloodPressureBuilder extends StatelessWidget {
-  const BloodPressureBuilder({required this.onData, required this.rangeType, super.key});
+  /// Create a loader for the measurements in the current range.
+  const BloodPressureBuilder({
+    super.key,
+    required this.onData,
+    required this.rangeType,
+  });
 
+  /// The build strategy once the measurement are loaded.
   final Widget Function(BuildContext context, UnmodifiableListView<BloodPressureRecord> records) onData;
+
+  /// Which measurements to load.
   final IntervallStoreManagerLocation rangeType;
   
   @override
lib/screens/elements/display_interval_picker.dart
@@ -4,9 +4,15 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 import 'package:intl/intl.dart';
 import 'package:provider/provider.dart';
 
+/// A selector for [IntervallStorage] values.
+///
+/// Allows selection [IntervallStorage.currentRange] and moving intervall wise
+/// in both directions.
 class IntervalPicker extends StatelessWidget {
+  /// Create a selector for [IntervallStorage] values.
   const IntervalPicker({super.key, required this.type});
 
+  /// Which range to display and modify.
   final IntervallStoreManagerLocation type;
   
   @override
lib/screens/elements/legacy_measurement_list.dart
@@ -11,8 +11,10 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 import 'package:intl/intl.dart';
 import 'package:provider/provider.dart';
 
+/// A old more compact [BloodPressureRecord] list, that lacks some of the new
+/// features.
 class LegacyMeasurementsList extends StatelessWidget {
-
+  /// Create a more compact measurement list without all new features.
   LegacyMeasurementsList(BuildContext context, {super.key}) {
     if (MediaQuery.of(context).size.width < 1000) {
       _tableElementsSizes = [33, 9, 9, 9, 30];
lib/screens/elements/measurement_graph.dart
@@ -37,7 +37,9 @@ class _LineChartState extends State<_LineChart> {
                 data.sort((a, b) => a.creationTime.compareTo(b.creationTime));
 
                 // calculate lines for graph
-                List<FlSpot> pulSpots = [], diaSpots = [], sysSpots = [];
+                final pulSpots = <FlSpot>[];
+                final diaSpots = <FlSpot>[];
+                final sysSpots = <FlSpot>[];
                 int maxValue = 0;
                 final int minValue = (settings.validateInputs ? 30 : 0);
                 /// Horizontally first value
@@ -256,6 +258,7 @@ class _LineChartState extends State<_LineChart> {
     );
 }
 
+// TODO: document
 class MeasurementGraph extends StatelessWidget {
 
   const MeasurementGraph({super.key, this.height = 290});
@@ -279,4 +282,3 @@ class MeasurementGraph extends StatelessWidget {
 extension Sum<T> on List<T> {
   double sum(num Function(T value) f) => fold<double>(0, (prev, e) => prev + f(e).toDouble());
 }
-
lib/screens/error_reporting_screen.dart
@@ -6,8 +6,12 @@ import 'package:path/path.dart';
 import 'package:sqflite/sqflite.dart';
 import 'package:url_launcher/url_launcher.dart';
 
+/// A static location to report errors to and disrupt the program flow in case
+/// there is the risk of data loss when continuing.
 class ErrorReporting {
   ErrorReporting._create();
+
+  /// Whether there is already an critical error displayed.
   static bool isErrorState = false;
 
   /// Replaces the application with an ErrorScreen
@@ -35,9 +39,12 @@ class ErrorReporting {
   }
 }
 
+/// A full [MaterialApp] that is especially safe against throwing errors and
+/// allows for debugging and data extraction.
 class ErrorScreen extends StatelessWidget {
   
   const ErrorScreen({super.key, required this.title, required this.text, required this.debugInfo});
+
   final String title;
   final String text;
   final PackageInfo debugInfo;
@@ -130,4 +137,4 @@ class ErrorScreen extends StatelessWidget {
       ),
     );
   
-}
\ No newline at end of file
+}
lib/screens/home_screen.dart
@@ -18,7 +18,10 @@ import 'package:provider/provider.dart';
 /// Is true during the first [AppHome.build] before creating the widget.
 bool _appStart = true;
 
+/// Central screen of the app with graph and measurement list that is the center
+/// of navigation.
 class AppHome extends StatelessWidget {
+  /// Create a home screen.
   const AppHome({super.key});
 
   @override
lib/screens/loading_screen.dart
@@ -4,7 +4,10 @@ import 'dart:ui';
 import 'package:flutter/material.dart';
 
 /// Loading page that is displayed on app start.
+///
+/// Contains a simplified app logo animation.
 class LoadingScreen extends StatelessWidget {
+  /// Loading page that is displayed on app start.
   const LoadingScreen({super.key});
 
   static const _duration = Duration(milliseconds: 250);
@@ -103,4 +106,4 @@ class _LogoPainter extends CustomPainter {
 
     return path;
   }
-}
\ No newline at end of file
+}
lib/main.dart
@@ -101,43 +101,47 @@ Future<Widget> _loadApp() async {
   ], child: const AppRoot(),);
 }
 
+/// Central [MaterialApp] widget of the app that sets the uniform style options.
 class AppRoot extends StatelessWidget {
+  /// Create the base for the entire app.
   const AppRoot({super.key});
 
   @override
-  Widget build(BuildContext context) => Consumer<Settings>(builder: (context, settings, child) => MaterialApp(
-        title: 'Blood Pressure App',
-        onGenerateTitle: (context) => AppLocalizations.of(context)!.title,
-        theme: _buildTheme(ColorScheme.fromSeed(
-          seedColor: settings.accentColor,
-        ),),
-        darkTheme: _buildTheme(ColorScheme.fromSeed(
-          seedColor: settings.accentColor,
-          brightness: Brightness.dark,
-          background: Colors.black,
-        ),),
-        themeMode: settings.themeMode,
-        localizationsDelegates: const [
-          AppLocalizations.delegate,
-          GlobalMaterialLocalizations.delegate,
-          GlobalCupertinoLocalizations.delegate,
-          GlobalWidgetsLocalizations.delegate,
-        ],
-        supportedLocales: AppLocalizations.supportedLocales,
-        locale: settings.language,
-        home: const AppHome(),
-      ),);
+  Widget build(BuildContext context) =>
+    Consumer<Settings>(builder: (context, settings, child) => MaterialApp(
+      title: 'Blood Pressure App',
+      onGenerateTitle: (context) => AppLocalizations.of(context)!.title,
+      theme: _buildTheme(ColorScheme.fromSeed(
+        seedColor: settings.accentColor,
+      ),),
+      darkTheme: _buildTheme(ColorScheme.fromSeed(
+        seedColor: settings.accentColor,
+        brightness: Brightness.dark,
+        background: Colors.black,
+      ),),
+      themeMode: settings.themeMode,
+      localizationsDelegates: const [
+        AppLocalizations.delegate,
+        GlobalMaterialLocalizations.delegate,
+        GlobalCupertinoLocalizations.delegate,
+        GlobalWidgetsLocalizations.delegate,
+      ],
+      supportedLocales: AppLocalizations.supportedLocales,
+      locale: settings.language,
+      home: const AppHome(),
+    ),
+  );
 
   ThemeData _buildTheme(ColorScheme colorScheme) {
     final inputBorder = OutlineInputBorder(
-        borderSide: BorderSide(
-          width: 3,
-          // Through black background outlineVariant has enough contrast.
-          color: (colorScheme.background == Colors.black)
-              ? colorScheme.outlineVariant
-              : colorScheme.outline,
-        ),
-        borderRadius: BorderRadius.circular(20),
+      borderSide: BorderSide(
+        width: 3,
+        // Through black background outlineVariant has enough contrast.
+        color: (colorScheme.background == Colors.black)
+            ? colorScheme.outlineVariant
+            : colorScheme.outline,
+      ),
+      borderRadius: BorderRadius.circular(20),
     );
 
     return ThemeData(
test/model/export_import/column_test.dart
@@ -67,7 +67,7 @@ void main() {
             break;
           case RowDataFieldType.needlePin:
             expect(decoded.$2, isA<MeasurementNeedlePin>().having(
-                    (p0) => p0.toJson(), 'pin', r.needlePin?.toJson(),),);
+                    (p0) => p0.toMap(), 'pin', r.needlePin?.toMap(),),);
             break;
         }
       }
@@ -134,7 +134,7 @@ void main() {
             break;
           case RowDataFieldType.needlePin:
             expect(decoded?.$2, isA<MeasurementNeedlePin>().having(
-                    (p0) => p0.toJson(), 'pin', r.needlePin?.toJson(),),);
+                    (p0) => p0.toMap(), 'pin', r.needlePin?.toMap(),),);
             break;
           case null:
             break;
@@ -182,4 +182,4 @@ BloodPressureRecord _filledRecord() => mockRecord(
   pul: 789,
   note: 'test',
   pin: Colors.pink,
-);
\ No newline at end of file
+);
test/model/export_import/csv_converter_test.dart
@@ -320,4 +320,4 @@ List<BloodPressureRecord>? failParse(RecordParsingError error) {
     case RecordParsingErrorUnparsableField():
       fail('Parsing failed because field ${error.fieldContents} in line ${error.lineNumber} is not parsable.');
   }
-}
\ No newline at end of file
+}
test/model/export_import/record_formatter_test.dart
@@ -26,7 +26,7 @@ void main() {
       expect(ScriptedFormatter(r'$SYS',).encode(testRecord), testRecord.systolic.toString());
       expect(ScriptedFormatter(r'$DIA',).encode(testRecord), testRecord.diastolic.toString());
       expect(ScriptedFormatter(r'$PUL',).encode(testRecord), testRecord.pulse.toString());
-      expect(ScriptedFormatter(r'$COLOR',).encode(testRecord), jsonEncode(testRecord.needlePin!.toJson()));
+      expect(ScriptedFormatter(r'$COLOR',).encode(testRecord), jsonEncode(testRecord.needlePin!.toMap()));
       expect(ScriptedFormatter(r'$NOTE',).encode(testRecord), testRecord.notes);
       expect(ScriptedFormatter(r'$TIMESTAMP',).encode(testRecord), testRecord.creationTime.millisecondsSinceEpoch.toString());
       expect(ScriptedFormatter(r'$SYS$DIA$PUL',).encode(testRecord), (testRecord.systolic.toString()
@@ -136,4 +136,4 @@ BloodPressureRecord mockRecord({
     dia,
     pul,
     note ?? '',
-    needlePin: pin == null ? null : MeasurementNeedlePin(pin),);
\ No newline at end of file
+    needlePin: pin == null ? null : MeasurementNeedlePin(pin),);
test/model/medicine/intake_history_test.dart
@@ -169,4 +169,4 @@ void main() {
       expect(deserializedHistory, history);
     });
   });
-}
\ No newline at end of file
+}
test/model/medicine/medicine_intake_test.dart
@@ -60,4 +60,4 @@ MedicineIntake mockIntake({
     medicine: medicine ?? mockMedicine(),
     dosis: dosis,
     timestamp: timeMs == null ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(timeMs),
-);
\ No newline at end of file
+);
test/model/medicine/medicine_test.dart
@@ -64,4 +64,4 @@ Medicine mockMedicine({
   final med = Medicine(_meds.length, designation: designation, color: color, defaultDosis: defaultDosis);
   _meds.add(med);
   return med;
-}
\ No newline at end of file
+}
test/model/analyzer_test.dart
@@ -62,4 +62,4 @@ void main() {
       expect((m.lastDay), DateTime.fromMillisecondsSinceEpoch(9000000));
     });
   });
-}
\ No newline at end of file
+}
test/model/config_db_test.dart
@@ -80,4 +80,4 @@ void main() {
       expect(newSettings.toJson(), initialSettingsJson);
     });
   });
-}
\ No newline at end of file
+}
test/model/convert_util_test.dart
@@ -122,4 +122,4 @@ void main() {
       expect(ConvertUtil.parseThemeMode(null), null);
     });
   });
-}
\ No newline at end of file
+}
test/model/intervall_store_test.dart
@@ -98,4 +98,4 @@ void main() {
     });
   });
 
-}
\ No newline at end of file
+}
test/model/json_serialization_test.dart
@@ -347,4 +347,4 @@ void main() {
       expect(v2.userColumns.length, ExportColumnsManager().userColumns.length);
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/settings/dropdown_list_tile_test.dart
@@ -74,4 +74,4 @@ void main() {
       expect(callCount, 1);
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/settings/input_list_tile_test.dart
@@ -77,4 +77,4 @@ void main() {
       expect(callCount, 1);
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/settings/number_input_list_tile_test.dart
@@ -110,4 +110,4 @@ void main() {
       expect(callCount, 4);
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/settings/slider_list_tile_test.dart
@@ -55,4 +55,4 @@ void main() {
       expect(callCount, 1);
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/settings/titled_column_test.dart
@@ -44,4 +44,4 @@ void main() {
       );
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/add_export_column_dialoge_test.dart
@@ -138,4 +138,4 @@ void main() {
     });
   });
 
-}
\ No newline at end of file
+}
test/ui/components/add_measurement_dialoge_test.dart
@@ -480,4 +480,4 @@ void main() {
       expect(find.descendant(of: fourthFocusedTextFormField, matching: find.text('Systolic')), findsWidgets);
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/color_picker_test.dart
@@ -36,4 +36,4 @@ void main() {
       expect(onColorSelectedCallCount, 1);
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/enter_timeformat_dialoge_test.dart
@@ -91,4 +91,4 @@ void main() {
       expect(result, 'test text!');
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/input_dialoge_test.dart
@@ -161,4 +161,4 @@ void main() {
       expect(result, null);
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/measurement_list_entry_test.dart
@@ -62,4 +62,4 @@ void main() {
       expect(find.text('null'), findsNothing);
     });
   });
-}
\ No newline at end of file
+}
test/ui/components/util.dart
@@ -24,4 +24,4 @@ Future<void> loadDialoge(WidgetTester tester, void Function(BuildContext context
       TextButton(onPressed: () => dialogeStarter(context), child: Text(dialogeStarterText)),),),);
   await tester.tap(find.text(dialogeStarterText));
   await tester.pumpAndSettle();
-}
\ No newline at end of file
+}
test/ui/statistics_test.dart
@@ -88,4 +88,4 @@ Future<void> _initStatsPage(WidgetTester widgetTester, List<BloodPressureRecord>
       ),
   ),);
   await widgetTester.pumpAndSettle();
-}
\ No newline at end of file
+}
test/ram_only_implementations.dart
@@ -47,4 +47,4 @@ class RamBloodPressureModel extends ChangeNotifier implements BloodPressureModel
   Future<void> addAndExport(BuildContext context, BloodPressureRecord record) async {
     add(record);
   }
-}
\ No newline at end of file
+}
analysis_options.yaml
@@ -22,7 +22,7 @@ linter:
     - eol_at_end_of_file
     - leading_newlines_in_multiline_strings
     - library_annotations
-    - lines_longer_than_80_chars
+    # TODO: - lines_longer_than_80_chars
     - matching_super_parameters
     - no_literal_bool_comparisons
     - noop_primitive_operations
pubspec.yaml
@@ -8,24 +8,23 @@ environment:
   sdk: '>=3.0.2 <4.0.0'
 
 dependencies:
+  csv: ^5.0.2
+  collection: ^1.17.1
+  intl: ^0.18.0
   flutter:
     sdk: flutter
   flutter_localizations:
     sdk: flutter
-  provider: ^6.0.0  # MIT
-  sqflite:  # BSD-2-Clause
-  path:  # BSD-3-Clause
-
-  intl: ^0.18.0  # BSD-3-Clause
-  fl_chart: ^0.63.0  # MIT
-  csv: ^5.0.2  # MIT
-  url_launcher: ^6.1.11  # BSD-3-Clause
-  shared_preferences: ^2.1.1  # BSD-3-Clause
+  flutter_markdown: ^0.6.17
+  fl_chart: ^0.63.0
+  function_tree: ^0.9.0
+  provider: ^6.0.0
+  path:
   pdf: ^3.10.4
   package_info_plus: ^4.0.2
-  function_tree: ^0.9.0
-  flutter_markdown: ^0.6.17
-  collection: ^1.17.1
+  sqflite:
+  shared_preferences: ^2.1.1
+  url_launcher: ^6.1.11
 
   # can become one custom dependency
   file_picker: ^5.2.11  # MIT
@@ -34,9 +33,9 @@ dependencies:
   fluttertoast: ^8.2.4
 
 dev_dependencies:
+  file: any
   flutter_test:
     sdk: flutter
-  file: any
   flutter_lints: ^2.0.0
   mockito: ^5.4.1
   sqflite_common_ffi: ^2.3.0