diff --git a/lib/view/pages/settings/sections/appearance_section.dart b/lib/view/pages/settings/sections/appearance_section.dart index 137757b..85cb8c3 100644 --- a/lib/view/pages/settings/sections/appearance_section.dart +++ b/lib/view/pages/settings/sections/appearance_section.dart @@ -5,6 +5,7 @@ import '../../../../state/app/modules/settings/bloc/settings_cubit.dart'; import '../../../../storage/haptic_settings.dart'; import '../../../../theming/app_theme.dart'; import '../../../../utils/haptics.dart'; +import '../widgets/settings_dropdown_tile.dart'; class AppearanceSection extends StatelessWidget { const AppearanceSection({super.key}); @@ -14,57 +15,27 @@ class AppearanceSection extends StatelessWidget { final settings = context.watch(); return Column( children: [ - ListTile( - leading: const Icon(Icons.dark_mode_outlined), - title: const Text('Farbgebung'), - trailing: DropdownButton( - value: settings.val().appTheme, - icon: const Icon(Icons.arrow_drop_down), - items: ThemeMode.values - .map( - (e) => DropdownMenuItem( - value: e, - enabled: e != settings.val().appTheme, - child: Row( - children: [ - Icon(AppTheme.getDisplayOptions(e).icon), - const SizedBox(width: 10), - Text(AppTheme.getDisplayOptions(e).displayName), - ], - ), - ), - ) - .toList(), - onChanged: (e) => settings.val(write: true).appTheme = e!, - ), + SettingsDropdownTile( + icon: Icons.dark_mode_outlined, + title: 'Farbgebung', + value: settings.val().appTheme, + options: ThemeMode.values, + optionIcon: (e) => AppTheme.getDisplayOptions(e).icon, + optionLabel: (e) => AppTheme.getDisplayOptions(e).displayName, + onChanged: (e) => settings.val(write: true).appTheme = e, ), - ListTile( - leading: const Icon(Icons.vibration_outlined), - title: const Text('Haptisches Feedback'), - trailing: DropdownButton( - value: settings.val().hapticSettings.level, - icon: const Icon(Icons.arrow_drop_down), - items: HapticLevel.values - .map( - (e) => DropdownMenuItem( - value: e, - enabled: e != settings.val().hapticSettings.level, - child: Row( - children: [ - Icon(_hapticIcon(e)), - const SizedBox(width: 10), - Text(_hapticLabel(e)), - ], - ), - ), - ) - .toList(), - onChanged: (e) { - settings.val(write: true).hapticSettings.level = e!; - // Sofortiges Probe-Feedback in der neu gewählten Stufe. - Haptics.longPress(); - }, - ), + SettingsDropdownTile( + icon: Icons.vibration_outlined, + title: 'Haptisches Feedback', + value: settings.val().hapticSettings.level, + options: HapticLevel.values, + optionIcon: _hapticIcon, + optionLabel: _hapticLabel, + onChanged: (e) { + settings.val(write: true).hapticSettings.level = e; + // Sofortiges Probe-Feedback in der neu gewählten Stufe. + Haptics.longPress(); + }, ), ], ); diff --git a/lib/view/pages/settings/sections/timetable_section.dart b/lib/view/pages/settings/sections/timetable_section.dart index 315031c..febbb6d 100644 --- a/lib/view/pages/settings/sections/timetable_section.dart +++ b/lib/view/pages/settings/sections/timetable_section.dart @@ -5,6 +5,7 @@ import '../../../../routing/app_routes.dart'; import '../../../../state/app/modules/settings/bloc/settings_cubit.dart'; import '../../../../view/pages/timetable/data/timetable_name_mode.dart'; import '../widgets/settings_checkbox_tile.dart'; +import '../widgets/settings_dropdown_tile.dart'; class TimetableSection extends StatelessWidget { const TimetableSection({super.key}); @@ -15,33 +16,15 @@ class TimetableSection extends StatelessWidget { final timetableSettings = settings.val().timetableSettings; return Column( children: [ - ListTile( - leading: const Icon(Icons.abc_outlined), - title: const Text('Fachbezeichnung'), - trailing: DropdownButton( - value: timetableSettings.timetableNameMode, - icon: const Icon(Icons.arrow_drop_down), - items: TimetableNameMode.values - .map( - (e) => DropdownMenuItem( - value: e, - enabled: e != timetableSettings.timetableNameMode, - child: Row( - children: [ - Icon(TimetableNameModes.getDisplayOptions(e).icon), - const SizedBox(width: 10), - Text( - TimetableNameModes.getDisplayOptions(e).displayName, - ), - ], - ), - ), - ) - .toList(), - onChanged: (value) => - settings.val(write: true).timetableSettings.timetableNameMode = - value!, - ), + SettingsDropdownTile( + icon: Icons.abc_outlined, + title: 'Fachbezeichnung', + value: timetableSettings.timetableNameMode, + options: TimetableNameMode.values, + optionIcon: (e) => TimetableNameModes.getDisplayOptions(e).icon, + optionLabel: (e) => TimetableNameModes.getDisplayOptions(e).displayName, + onChanged: (e) => + settings.val(write: true).timetableSettings.timetableNameMode = e, ), SettingsCheckboxTile( icon: Icons.calendar_view_day_outlined, diff --git a/lib/view/pages/settings/widgets/settings_dropdown_tile.dart b/lib/view/pages/settings/widgets/settings_dropdown_tile.dart new file mode 100644 index 0000000..8500856 --- /dev/null +++ b/lib/view/pages/settings/widgets/settings_dropdown_tile.dart @@ -0,0 +1,56 @@ +import 'package:flutter/material.dart'; + +/// Settings row with a trailing [DropdownButton]. Each option renders as an +/// icon + label row; the currently selected option is disabled in the menu, +/// matching the settings styling. [onChanged] receives the picked (non-null) +/// value. +class SettingsDropdownTile extends StatelessWidget { + final IconData icon; + final String title; + final T value; + final List options; + final IconData Function(T) optionIcon; + final String Function(T) optionLabel; + final ValueChanged onChanged; + + const SettingsDropdownTile({ + required this.icon, + required this.title, + required this.value, + required this.options, + required this.optionIcon, + required this.optionLabel, + required this.onChanged, + super.key, + }); + + @override + Widget build(BuildContext context) { + return ListTile( + leading: Icon(icon), + title: Text(title), + trailing: DropdownButton( + value: value, + icon: const Icon(Icons.arrow_drop_down), + items: options + .map( + (e) => DropdownMenuItem( + value: e, + enabled: e != value, + child: Row( + children: [ + Icon(optionIcon(e)), + const SizedBox(width: 10), + Text(optionLabel(e)), + ], + ), + ), + ) + .toList(), + onChanged: (e) { + if (e != null) onChanged(e); + }, + ), + ); + } +}