From f709d72f5043576926c7bfdb5c1f3cc10d2a0672 Mon Sep 17 00:00:00 2001 From: yandrik Date: Thu, 20 Nov 2025 20:01:46 +0100 Subject: [PATCH] feat: add date input fields to settings_page --- lib/settings_page.dart | 124 ++++++++++++++++++++++++++++++++++------- pubspec.lock | 30 +++++----- 2 files changed, 118 insertions(+), 36 deletions(-) diff --git a/lib/settings_page.dart b/lib/settings_page.dart index 0d112a1..45a5dd3 100644 --- a/lib/settings_page.dart +++ b/lib/settings_page.dart @@ -166,12 +166,61 @@ class _SettingsPageState extends State { final TextEditingController _urlController = TextEditingController(); final TextEditingController _usernameController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); + final TextEditingController _historyDaysController = TextEditingController(); + final TextEditingController _historyHoursController = TextEditingController(); + + void _syncHistoryControllers(Duration duration) { + _historyDaysController.text = duration.inDays.toString(); + _historyHoursController.text = (duration.inHours % 24).toString(); + } + + void _showSnackBar(BuildContext context, String message) { + if (!mounted) return; + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(message))); + } + + void _maybeWarnLongDuration(BuildContext context, Duration duration) { + if (duration.inDays > 4) { + _showSnackBar(context, + 'Warning:\nLong durations might cause slowdowns and high data usage!'); + } + } + + void _applyDuration(BuildContext context, Duration duration) { + if (duration.inHours < 1) { + _showSnackBar( + context, 'Please pick a duration of at least 1 hour (>= 1h)!'); + return; + } + + context.read().updateSettings(historyTime: duration); + _maybeWarnLongDuration(context, duration); + } + + void _applyManualDuration(BuildContext context) { + final daysText = _historyDaysController.text.trim(); + final hoursText = _historyHoursController.text.trim(); + + final days = int.tryParse(daysText.isEmpty ? '0' : daysText); + final hours = int.tryParse(hoursText.isEmpty ? '0' : hoursText); + + if (days == null || hours == null) { + _showSnackBar(context, 'Days and hours must be whole numbers.'); + return; + } + + final duration = Duration(days: days, hours: hours); + _applyDuration(context, duration); + } @override void dispose() { _urlController.dispose(); _usernameController.dispose(); _passwordController.dispose(); + _historyDaysController.dispose(); + _historyHoursController.dispose(); super.dispose(); } @@ -184,11 +233,13 @@ class _SettingsPageState extends State { _urlController.text = state.url; _usernameController.text = state.username; _passwordController.text = state.password; + _syncHistoryControllers(state.historyTime); }, builder: (context, state) { _urlController.text = state.url; _usernameController.text = state.username; _passwordController.text = state.password; + _syncHistoryControllers(state.historyTime); return SingleChildScrollView( child: Column( children: [ @@ -279,37 +330,68 @@ class _SettingsPageState extends State { const SizedBox(height: 16), ElevatedButton( onPressed: () async { - final settingsCubit = context.read(); var resultingDuration = await showDurationPicker( context: context, initialTime: state.historyTime, baseUnit: BaseUnit.hour, ); if (resultingDuration != null) { - if (resultingDuration.inHours == 0) { - if (context.mounted) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text( - 'Please pick a duration of 1h or more!'))); - } - } else { - settingsCubit.updateSettings( - historyTime: resultingDuration); - } - - if (resultingDuration.inDays > 4) { - if (context.mounted) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text( - 'Warning:\nLong durations might cause slowdowns and high data usage!'))); - } - } + _applyDuration(context, resultingDuration); } }, child: Text( 'Set Time to Load Points (current: ${formatDuration(state.historyTime)})')), + const SizedBox(height: 12), + Align( + alignment: Alignment.centerLeft, + child: Text( + 'Or enter duration manually:', + style: Theme.of(context).textTheme.titleMedium, + ), + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: TextField( + controller: _historyDaysController, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + ], + decoration: const InputDecoration( + labelText: 'Days', + border: OutlineInputBorder(), + suffixText: 'd', + ), + ), + ), + const SizedBox(width: 12), + Expanded( + child: TextField( + controller: _historyHoursController, + keyboardType: TextInputType.number, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + ], + decoration: const InputDecoration( + labelText: 'Hours', + border: OutlineInputBorder(), + suffixText: 'h', + ), + ), + ), + ], + ), + const SizedBox(height: 8), + Align( + alignment: Alignment.centerLeft, + child: ElevatedButton.icon( + onPressed: () => _applyManualDuration(context), + icon: const Icon(Icons.edit_calendar), + label: const Text('Apply Duration'), + ), + ), const SizedBox(height: 16), Container( padding: const EdgeInsets.all(16), diff --git a/pubspec.lock b/pubspec.lock index cd2d4ce..7b47a42 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -157,10 +157,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.3" fast_immutable_collections: dependency: "direct main" description: @@ -348,26 +348,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" url: "https://pub.dev" source: hosted - version: "10.0.8" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -412,10 +412,10 @@ packages: dependency: transitive description: name: meta - sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" mgrs_dart: dependency: transitive description: @@ -681,10 +681,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.7" typed_data: dependency: transitive description: @@ -713,10 +713,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -774,5 +774,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.7.0 <4.0.0" + dart: ">=3.8.0-0 <4.0.0" flutter: ">=3.27.0"