feat: add date input fields to settings_page
This commit is contained in:
@ -166,12 +166,61 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
final TextEditingController _urlController = TextEditingController();
|
final TextEditingController _urlController = TextEditingController();
|
||||||
final TextEditingController _usernameController = TextEditingController();
|
final TextEditingController _usernameController = TextEditingController();
|
||||||
final TextEditingController _passwordController = 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
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_urlController.dispose();
|
_urlController.dispose();
|
||||||
_usernameController.dispose();
|
_usernameController.dispose();
|
||||||
_passwordController.dispose();
|
_passwordController.dispose();
|
||||||
|
_historyDaysController.dispose();
|
||||||
|
_historyHoursController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,11 +233,13 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
_urlController.text = state.url;
|
_urlController.text = state.url;
|
||||||
_usernameController.text = state.username;
|
_usernameController.text = state.username;
|
||||||
_passwordController.text = state.password;
|
_passwordController.text = state.password;
|
||||||
|
_syncHistoryControllers(state.historyTime);
|
||||||
},
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
_urlController.text = state.url;
|
_urlController.text = state.url;
|
||||||
_usernameController.text = state.username;
|
_usernameController.text = state.username;
|
||||||
_passwordController.text = state.password;
|
_passwordController.text = state.password;
|
||||||
|
_syncHistoryControllers(state.historyTime);
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@ -279,37 +330,68 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final settingsCubit = context.read<SettingsCubit>();
|
|
||||||
var resultingDuration = await showDurationPicker(
|
var resultingDuration = await showDurationPicker(
|
||||||
context: context,
|
context: context,
|
||||||
initialTime: state.historyTime,
|
initialTime: state.historyTime,
|
||||||
baseUnit: BaseUnit.hour,
|
baseUnit: BaseUnit.hour,
|
||||||
);
|
);
|
||||||
if (resultingDuration != null) {
|
if (resultingDuration != null) {
|
||||||
if (resultingDuration.inHours == 0) {
|
_applyDuration(context, resultingDuration);
|
||||||
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!')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Set Time to Load Points (current: ${formatDuration(state.historyTime)})')),
|
'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),
|
const SizedBox(height: 16),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
|
|||||||
30
pubspec.lock
30
pubspec.lock
@ -157,10 +157,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
|
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.3.3"
|
||||||
fast_immutable_collections:
|
fast_immutable_collections:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -348,26 +348,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.8"
|
version: "11.0.2"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.9"
|
version: "3.0.10"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_testing
|
name: leak_tracker_testing
|
||||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -412,10 +412,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.16.0"
|
version: "1.17.0"
|
||||||
mgrs_dart:
|
mgrs_dart:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -681,10 +681,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.4"
|
version: "0.7.7"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -713,10 +713,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.2.0"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -774,5 +774,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.7.0 <4.0.0"
|
dart: ">=3.8.0-0 <4.0.0"
|
||||||
flutter: ">=3.27.0"
|
flutter: ">=3.27.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user