added selector for repeat-interval. Needs UI-polish though..
This commit is contained in:
parent
db39eeea55
commit
43f95cb321
@ -6,7 +6,7 @@ A Reminder based on todo.txt synced via nextcloud
|
||||
|
||||
- [x] make repeat-datatype (like: daily, weekly on mo/th/fr, bi-monthly, etc.)
|
||||
- [x] define isomorphism for 'repeat:'-meta-tag
|
||||
- [ ] add interface for repeat-datatype in addReminder.dart
|
||||
- [x] add interface for repeat-datatype in addReminder.dart
|
||||
- [x] save/load data to/from disk
|
||||
- [x] adding/removing tasks
|
||||
- [x] respect ordering that was used when starting the app when saving.
|
||||
|
@ -1,7 +1,10 @@
|
||||
import 'package:date_field/date_field.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:nextcloud_reminder/repeating_task.dart';
|
||||
import 'package:nextcloud_reminder/types/repeat.dart';
|
||||
import 'package:nextcloud_reminder/types/tasks.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class AddTaskWidget extends StatefulWidget {
|
||||
const AddTaskWidget({super.key, this.restorationId, required this.onSave});
|
||||
@ -15,11 +18,14 @@ class AddTaskWidget extends StatefulWidget {
|
||||
|
||||
//TODO: make _repeat changeable.
|
||||
|
||||
class _AddTaskWidgetState extends State<AddTaskWidget> with RestorationMixin {
|
||||
class _AddTaskWidgetState extends State<AddTaskWidget> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _titleController = TextEditingController();
|
||||
final int _repeat = 1;
|
||||
final RestorableDateTime _beginDate = RestorableDateTime(DateTime.now());
|
||||
static _emptyRepetition() {
|
||||
return Tuple2(TextEditingController(text: "1"), ValueNotifier(DateInterval.daily));
|
||||
}
|
||||
final List<Tuple2<TextEditingController,ValueNotifier<DateInterval>>> _repeatEveryController = [_emptyRepetition()];
|
||||
DateTime _beginDate = DateTime.now();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@ -27,51 +33,43 @@ class _AddTaskWidgetState extends State<AddTaskWidget> with RestorationMixin {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
String? get restorationId => widget.restorationId;
|
||||
|
||||
late final RestorableRouteFuture<DateTime?> _restorableDatePickerRouteFuture =
|
||||
RestorableRouteFuture<DateTime?>(
|
||||
onComplete: _selectDate,
|
||||
onPresent: (NavigatorState navigator, Object? arguments) {
|
||||
return navigator.restorablePush(
|
||||
_datePickerRoute,
|
||||
arguments: _beginDate.value.millisecondsSinceEpoch,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
static Route<DateTime> _datePickerRoute(
|
||||
BuildContext context,
|
||||
Object? arguments,
|
||||
) {
|
||||
return DialogRoute<DateTime>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return DatePickerDialog(
|
||||
restorationId: 'date_picker_dialog',
|
||||
initialEntryMode: DatePickerEntryMode.calendarOnly,
|
||||
initialDate: DateTime.fromMillisecondsSinceEpoch(arguments! as int),
|
||||
firstDate: DateTime(2000),
|
||||
lastDate: DateTime(2100),
|
||||
);
|
||||
},
|
||||
);
|
||||
String _prettyInterval(DateInterval d) {
|
||||
switch (d) {
|
||||
default:
|
||||
return d.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
|
||||
registerForRestoration(_beginDate, 'selected_date');
|
||||
registerForRestoration(
|
||||
_restorableDatePickerRouteFuture, 'date_picker_route_future');
|
||||
}
|
||||
|
||||
void _selectDate(DateTime? newSelectedDate) {
|
||||
if (newSelectedDate != null) {
|
||||
setState(() {
|
||||
_beginDate.value = newSelectedDate;
|
||||
});
|
||||
}
|
||||
Widget _repeatBuilder(BuildContext context, Tuple2<TextEditingController,ValueNotifier<DateInterval>> data) {
|
||||
return Row(
|
||||
children: [
|
||||
Text("Repeat every " ),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: TextFormField(
|
||||
controller: data.item1,
|
||||
decoration: const InputDecoration(
|
||||
hintText: "1",
|
||||
),
|
||||
keyboardType: const TextInputType.numberWithOptions(signed: false, decimal: false),
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: DropdownButton<DateInterval>(
|
||||
items: DateInterval.values.map((v) => DropdownMenuItem(value: v, child: Text(_prettyInterval(v)))).toList(),
|
||||
onChanged: (v) => setState(() {
|
||||
data.item2.value = v ?? data.item2.value;
|
||||
}),
|
||||
value: data.item2.value,
|
||||
),
|
||||
),
|
||||
IconButton(onPressed: () => setState(() {
|
||||
_repeatEveryController.remove(data);
|
||||
}), icon: Icon(Icons.remove, color: Theme.of(context).errorColor,)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -98,21 +96,21 @@ class _AddTaskWidgetState extends State<AddTaskWidget> with RestorationMixin {
|
||||
labelText: "Taskname"
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: const BoxDecoration(),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Begin: ", style: Theme.of(context).textTheme.labelLarge),
|
||||
Expanded(
|
||||
child: Text(Task.formatDate(_beginDate.value))
|
||||
|
||||
DateTimeField(
|
||||
onDateSelected: (v) => setState(() { _beginDate = v; }),
|
||||
selectedDate: _beginDate,
|
||||
decoration: const InputDecoration(
|
||||
suffixIcon: Icon(Icons.event_note),
|
||||
labelText: "Begin"
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => _restorableDatePickerRouteFuture.present(),
|
||||
icon: Icon(Icons.date_range,
|
||||
color: Theme.of(context).focusColor))
|
||||
]
|
||||
)
|
||||
mode: DateTimeFieldPickerMode.date,
|
||||
),
|
||||
] + _repeatEveryController.map((c) => _repeatBuilder(context,c)).toList()
|
||||
+ [
|
||||
ElevatedButton(onPressed: () => setState(() {
|
||||
_repeatEveryController.add(_emptyRepetition());
|
||||
}), child: const Text("add repetition")),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: ElevatedButton(
|
||||
@ -124,8 +122,16 @@ class _AddTaskWidgetState extends State<AddTaskWidget> with RestorationMixin {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Task added.')),
|
||||
);
|
||||
var repeats = _repeatEveryController.map((e) => RepeatInterval(interval: e.item2.value, every: int.parse(e.item1.text))).toList();
|
||||
var meta = repeats.map((e) => e.toString()).join("/");
|
||||
widget.onSave(RepeatingTask(
|
||||
task: TaskExtra(title: _titleController.text, begin: _beginDate.value, repeat: [RepeatInterval(interval: DateInterval.daily)],)));
|
||||
task: TaskExtra(
|
||||
title: _titleController.text,
|
||||
begin: _beginDate,
|
||||
meta: {"repeat": meta},
|
||||
repeat: repeats,
|
||||
)
|
||||
));
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
|
14
pubspec.lock
14
pubspec.lock
@ -43,6 +43,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
date_field:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: date_field
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -93,6 +100,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.2"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.17.0"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -41,6 +41,7 @@ dependencies:
|
||||
tuple: ^2.0.1
|
||||
flutter_window_close: ^0.2.2
|
||||
collection: ^1.16.0
|
||||
date_field: ^3.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user