feat: add date input fields to settings_page

This commit is contained in:
2025-11-20 20:01:46 +01:00
parent d7eefa32fe
commit f709d72f50
2 changed files with 118 additions and 36 deletions

View File

@ -166,12 +166,61 @@ class _SettingsPageState extends State<SettingsPage> {
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<SettingsCubit>().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<SettingsPage> {
_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<SettingsPage> {
const SizedBox(height: 16),
ElevatedButton(
onPressed: () async {
final settingsCubit = context.read<SettingsCubit>();
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),

View File

@ -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"