Time
This commit is contained in:
+2
-1
@@ -1,9 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class Todo {
|
class Todo {
|
||||||
Todo({required this.title, required this.widget, required this.checked});
|
Todo({required this.title, required this.widget, required this.checked, required this.dueTime});
|
||||||
|
|
||||||
String title;
|
String title;
|
||||||
Widget widget;
|
Widget widget;
|
||||||
|
DateTime dueTime;
|
||||||
bool checked;
|
bool checked;
|
||||||
}
|
}
|
||||||
+101
-39
@@ -1,57 +1,119 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:todoapp/elems/todo.dart';
|
import 'package:todoapp/elems/todo.dart';
|
||||||
|
import 'package:todoapp/modals/datepickermodal.dart';
|
||||||
|
import 'package:todoapp/modals/timepickermodal.dart';
|
||||||
import 'package:todoapp/providers/todoprovider.dart';
|
import 'package:todoapp/providers/todoprovider.dart';
|
||||||
|
|
||||||
class AddTodoModal {
|
class AddTodoModal {
|
||||||
static String tempValue = "";
|
|
||||||
|
|
||||||
static void add(BuildContext context) {
|
static void add(BuildContext context) {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
showDragHandle: true,
|
showDragHandle: true,
|
||||||
useSafeArea: true,
|
useSafeArea: true,
|
||||||
scrollControlDisabledMaxHeightRatio: 1,
|
scrollControlDisabledMaxHeightRatio: 1,
|
||||||
builder: (context) => Padding(
|
builder: (context) => const ModalCreateTodo(),
|
||||||
padding: const EdgeInsets.only(left: 30, right: 30),
|
);
|
||||||
child: Column(
|
}
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
}
|
||||||
children: [
|
|
||||||
TextFormField(
|
class ModalCreateTodo extends StatefulWidget {
|
||||||
autofocus: true,
|
const ModalCreateTodo({super.key});
|
||||||
decoration: const InputDecoration(labelText: "Title"),
|
|
||||||
onChanged: (value) => tempValue = value,
|
@override
|
||||||
onFieldSubmitted: (value) {
|
State<ModalCreateTodo> createState() => _ModalCreateTodoState();
|
||||||
context.read<TodoProvider>().addTodo(value);
|
}
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
class _ModalCreateTodoState extends State<ModalCreateTodo> {
|
||||||
|
String tempValue = "";
|
||||||
|
DateTime tempDateSelect = DateTime.now();
|
||||||
|
TimeOfDay tempTimeSelect = TimeOfDay.now();
|
||||||
|
|
||||||
|
String formatNumber(int number) {
|
||||||
|
if (number < 10) {
|
||||||
|
return "0$number";
|
||||||
|
}
|
||||||
|
return number.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime combineTime() {
|
||||||
|
return DateTime(tempDateSelect.year, tempDateSelect.month,
|
||||||
|
tempDateSelect.day, tempTimeSelect.hour, tempTimeSelect.minute);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 30, right: 30),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
autofocus: true,
|
||||||
|
decoration: const InputDecoration(labelText: "Title"),
|
||||||
|
onChanged: (value) => tempValue = value,
|
||||||
|
onFieldSubmitted: (value) {
|
||||||
|
context.read<TodoProvider>().addTodo(value, combineTime());
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
FilledButton.tonal(
|
||||||
|
onPressed: () async {
|
||||||
|
tempDateSelect =
|
||||||
|
(await DatePickerModal.add(context, tempDateSelect))!;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.date_range),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
Text(
|
||||||
|
"${tempDateSelect.year}-${formatNumber(tempDateSelect.month)}-${formatNumber(tempDateSelect.day)}")
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20,),
|
),
|
||||||
SegmentedButton(
|
const SizedBox(height: 10),
|
||||||
segments: const [
|
FilledButton.tonal(
|
||||||
ButtonSegment(
|
onPressed: () async {
|
||||||
|
tempTimeSelect =
|
||||||
|
(await TimePickerModal.add(context, tempTimeSelect))!;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.timer),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
Text(
|
||||||
|
"${formatNumber(tempTimeSelect.hour)}:${formatNumber(tempTimeSelect.minute)}")
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
SegmentedButton(
|
||||||
|
segments: const [
|
||||||
|
ButtonSegment(
|
||||||
value: "Cancel",
|
value: "Cancel",
|
||||||
label: Text("Cancel"),
|
label: Text("Cancel"),
|
||||||
icon: Icon(Icons.cancel)
|
icon: Icon(Icons.cancel)),
|
||||||
),
|
ButtonSegment(
|
||||||
ButtonSegment(
|
value: "Save", label: Text("Save"), icon: Icon(Icons.save)),
|
||||||
value: "Save",
|
],
|
||||||
label: Text("Save"),
|
selected: const {"None"},
|
||||||
icon: Icon(Icons.save)
|
style: ButtonStyle(
|
||||||
),
|
iconColor: WidgetStatePropertyAll(
|
||||||
],
|
Theme.of(context).colorScheme.primary)),
|
||||||
selected: const {"None"},
|
onSelectionChanged: (p0) {
|
||||||
style: ButtonStyle(iconColor: WidgetStatePropertyAll(Theme.of(context).colorScheme.primary)),
|
if (p0.last == "Save") {
|
||||||
onSelectionChanged: (p0) {
|
context.read<TodoProvider>().addTodo(tempValue, combineTime());
|
||||||
if (p0.last == "Save") {
|
}
|
||||||
context.read<TodoProvider>().addTodo(tempValue);
|
Navigator.pop(context);
|
||||||
}
|
},
|
||||||
Navigator.pop(context);
|
)
|
||||||
},
|
],
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DatePickerModal {
|
||||||
|
static Future<DateTime?> add(BuildContext context, DateTime initial) async {
|
||||||
|
DateTime? selected = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: initial,
|
||||||
|
firstDate: DateTime.now(),
|
||||||
|
lastDate: DateTime(DateTime.now().year+10, 12, 31),
|
||||||
|
);
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
+127
-50
@@ -1,65 +1,142 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:todoapp/elems/todo.dart';
|
import 'package:todoapp/elems/todo.dart';
|
||||||
|
import 'package:todoapp/modals/datepickermodal.dart';
|
||||||
|
import 'package:todoapp/modals/timepickermodal.dart';
|
||||||
import 'package:todoapp/providers/todoprovider.dart';
|
import 'package:todoapp/providers/todoprovider.dart';
|
||||||
|
|
||||||
class EditTodoModal {
|
class EditTodoModal {
|
||||||
static String tempValue = "";
|
static void add(BuildContext context, String title, DateTime dueTime) {
|
||||||
|
|
||||||
static void add(BuildContext context, String title) {
|
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
showDragHandle: true,
|
showDragHandle: true,
|
||||||
useSafeArea: true,
|
useSafeArea: true,
|
||||||
scrollControlDisabledMaxHeightRatio: 1,
|
scrollControlDisabledMaxHeightRatio: 1,
|
||||||
builder: (context) => Padding(
|
builder: (context) => ModalEditTodo(
|
||||||
padding: const EdgeInsets.only(left: 30, right: 30),
|
oldValue: title,
|
||||||
child: Column(
|
initDate: DateTime(dueTime.year, dueTime.month, dueTime.day),
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
initTime: TimeOfDay(hour: dueTime.hour, minute: dueTime.minute)),
|
||||||
children: [
|
);
|
||||||
TextFormField(
|
}
|
||||||
autofocus: true,
|
}
|
||||||
initialValue: title,
|
|
||||||
decoration: const InputDecoration(labelText: "Title"),
|
class ModalEditTodo extends StatefulWidget {
|
||||||
onChanged: (value) => tempValue = value,
|
const ModalEditTodo(
|
||||||
onFieldSubmitted: (value) {
|
{super.key,
|
||||||
context.read<TodoProvider>().updateTodo(title, value);
|
required this.oldValue,
|
||||||
Navigator.pop(context);
|
required this.initDate,
|
||||||
},
|
required this.initTime});
|
||||||
),
|
|
||||||
const SizedBox(height: 20,),
|
final String oldValue;
|
||||||
SegmentedButton(
|
final DateTime initDate;
|
||||||
segments: const [
|
final TimeOfDay initTime;
|
||||||
ButtonSegment(
|
|
||||||
value: "Delete",
|
@override
|
||||||
label: Text("Delete"),
|
State<ModalEditTodo> createState() => _ModalEditTodoState();
|
||||||
icon: Icon(Icons.delete)
|
}
|
||||||
),
|
|
||||||
ButtonSegment(
|
class _ModalEditTodoState extends State<ModalEditTodo> {
|
||||||
value: "Cancel",
|
String tempValue = "";
|
||||||
label: Text("Cancel"),
|
TimeOfDay tempTimeSelect = TimeOfDay.now();
|
||||||
icon: Icon(Icons.cancel)
|
DateTime tempDateSelect = DateTime.now();
|
||||||
),
|
|
||||||
ButtonSegment(
|
String formatNumber(int number) {
|
||||||
value: "Save",
|
if (number < 10) {
|
||||||
label: Text("Save"),
|
return "0$number";
|
||||||
icon: Icon(Icons.save)
|
}
|
||||||
),
|
return number.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime combineTime() {
|
||||||
|
return DateTime(tempDateSelect.year, tempDateSelect.month,
|
||||||
|
tempDateSelect.day, tempTimeSelect.hour, tempTimeSelect.minute);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool firstBuild = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (firstBuild) {
|
||||||
|
tempValue = widget.oldValue;
|
||||||
|
tempDateSelect = widget.initDate;
|
||||||
|
tempTimeSelect = widget.initTime;
|
||||||
|
firstBuild = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 30, right: 30),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
autofocus: true,
|
||||||
|
initialValue: widget.oldValue,
|
||||||
|
decoration: const InputDecoration(labelText: "Title"),
|
||||||
|
onChanged: (value) => tempValue = value,
|
||||||
|
onFieldSubmitted: (value) {
|
||||||
|
context.read<TodoProvider>().updateTodo(widget.oldValue, value, combineTime());
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
FilledButton.tonal(
|
||||||
|
onPressed: () async {
|
||||||
|
tempDateSelect =
|
||||||
|
(await DatePickerModal.add(context, tempDateSelect))!;
|
||||||
|
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
|
||||||
|
print(tempDateSelect);
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.date_range),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
Text(
|
||||||
|
"${tempDateSelect.year}-${formatNumber(tempDateSelect.month)}-${formatNumber(tempDateSelect.day)}")
|
||||||
],
|
],
|
||||||
selected: const {"None"},
|
),
|
||||||
style: ButtonStyle(iconColor: WidgetStatePropertyAll(Theme.of(context).colorScheme.primary)),
|
),
|
||||||
onSelectionChanged: (p0) {
|
const SizedBox(height: 10),
|
||||||
if (p0.last == "Save") {
|
FilledButton.tonal(
|
||||||
context.read<TodoProvider>().updateTodo(title, tempValue);
|
onPressed: () async {
|
||||||
} else if (p0.last == "Delete") {
|
tempTimeSelect =
|
||||||
context.read<TodoProvider>().removeTodo(title);
|
(await TimePickerModal.add(context, tempTimeSelect))!;
|
||||||
}
|
setState(() {});
|
||||||
Navigator.pop(context);
|
},
|
||||||
},
|
child: Row(
|
||||||
)
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
],
|
children: [
|
||||||
),
|
const Icon(Icons.timer),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
Text(
|
||||||
|
"${formatNumber(tempTimeSelect.hour)}:${formatNumber(tempTimeSelect.minute)}")
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
SegmentedButton(
|
||||||
|
segments: const [
|
||||||
|
ButtonSegment(
|
||||||
|
value: "Cancel",
|
||||||
|
label: Text("Cancel"),
|
||||||
|
icon: Icon(Icons.cancel)),
|
||||||
|
ButtonSegment(
|
||||||
|
value: "Save", label: Text("Save"), icon: Icon(Icons.save)),
|
||||||
|
],
|
||||||
|
selected: const {"None"},
|
||||||
|
style: ButtonStyle(
|
||||||
|
iconColor: WidgetStatePropertyAll(
|
||||||
|
Theme.of(context).colorScheme.primary)),
|
||||||
|
onSelectionChanged: (p0) {
|
||||||
|
if (p0.last == "Save") {
|
||||||
|
context.read<TodoProvider>().updateTodo(widget.oldValue, tempValue, combineTime());
|
||||||
|
}
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class TimePickerModal {
|
||||||
|
static Future<TimeOfDay?> add(BuildContext context, TimeOfDay initial) async {
|
||||||
|
TimeOfDay? timeSelect = await showTimePicker(
|
||||||
|
context: context,
|
||||||
|
initialTime: initial,
|
||||||
|
);
|
||||||
|
|
||||||
|
return timeSelect;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:todoapp/elems/todo.dart';
|
||||||
|
import 'package:todoapp/modals/datepickermodal.dart';
|
||||||
|
import 'package:todoapp/modals/timepickermodal.dart';
|
||||||
|
import 'package:todoapp/providers/todoprovider.dart';
|
||||||
|
|
||||||
@@ -4,24 +4,116 @@ import 'package:todoapp/modals/edittodomodal.dart';
|
|||||||
import 'package:todoapp/providers/todoprovider.dart';
|
import 'package:todoapp/providers/todoprovider.dart';
|
||||||
|
|
||||||
class TodoWidget extends StatefulWidget {
|
class TodoWidget extends StatefulWidget {
|
||||||
const TodoWidget({super.key, required this.checked, required this.title});
|
const TodoWidget(
|
||||||
|
{super.key,
|
||||||
|
required this.checked,
|
||||||
|
required this.title,
|
||||||
|
required this.dueTime});
|
||||||
|
|
||||||
final bool checked;
|
final bool checked;
|
||||||
final String title;
|
final String title;
|
||||||
|
final DateTime dueTime;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<TodoWidget> createState() => _TodoWidgetState();
|
State<TodoWidget> createState() => _TodoWidgetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TodoWidgetState extends State<TodoWidget> {
|
class _TodoWidgetState extends State<TodoWidget> {
|
||||||
|
String formatNumber(int number) {
|
||||||
|
if (number < 10) {
|
||||||
|
return "0$number";
|
||||||
|
}
|
||||||
|
return number.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<dynamic> buildDisplayString() {
|
||||||
|
DateTime today = DateTime.now();
|
||||||
|
DateTime due = widget.dueTime;
|
||||||
|
|
||||||
|
DateTime nowDay = DateTime(2000, 1, today.day);
|
||||||
|
DateTime dueDay = DateTime(2000, 1, due.day);
|
||||||
|
int diff = dueDay.difference(nowDay).inDays;
|
||||||
|
|
||||||
|
Map<int, String> monthList = {
|
||||||
|
1: "Jan",
|
||||||
|
2: "Feb",
|
||||||
|
3: "Mar",
|
||||||
|
4: "Apr",
|
||||||
|
5: "Mai",
|
||||||
|
6: "Jun",
|
||||||
|
7: "Jul",
|
||||||
|
8: "Aug",
|
||||||
|
9: "Sep",
|
||||||
|
10: "Okt",
|
||||||
|
11: "Nov",
|
||||||
|
12: "Dez"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (diff < 0) {
|
||||||
|
return [
|
||||||
|
"Over",
|
||||||
|
Colors.red,
|
||||||
|
Colors.white
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else if (diff < 1) {
|
||||||
|
return [
|
||||||
|
"Today ${formatNumber(due.hour)}:${formatNumber(due.minute)}",
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
|
Colors.black
|
||||||
|
];
|
||||||
|
} else if (diff < 2) {
|
||||||
|
return [
|
||||||
|
"Tomorrow ${formatNumber(due.hour)}:${formatNumber(due.minute)}",
|
||||||
|
Theme.of(context).colorScheme.inversePrimary,
|
||||||
|
Colors.white
|
||||||
|
];
|
||||||
|
} else if (diff < 7) {
|
||||||
|
return [
|
||||||
|
"In $diff days",
|
||||||
|
Theme.of(context).colorScheme.secondary.withOpacity(0.35),
|
||||||
|
Colors.white
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return [
|
||||||
|
"${monthList[due.month]} ${formatNumber(due.day)}, ${due.year}",
|
||||||
|
Theme.of(context).colorScheme.secondary.withOpacity(0.35),
|
||||||
|
Colors.white
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
EditTodoModal.add(context, widget.title);
|
EditTodoModal.add(context, widget.title, widget.dueTime);
|
||||||
},
|
},
|
||||||
child: CheckboxListTile(
|
child: CheckboxListTile(
|
||||||
value: widget.checked,
|
value: widget.checked,
|
||||||
|
subtitle: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding:
|
||||||
|
widget.checked ? EdgeInsets.zero : const EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: widget.checked
|
||||||
|
? const Color(0x00000000)
|
||||||
|
: buildDisplayString()[1],
|
||||||
|
borderRadius: BorderRadius.circular(10)),
|
||||||
|
child: Text(
|
||||||
|
buildDisplayString()[0],
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
widget.checked ? Colors.white : buildDisplayString()[2],
|
||||||
|
decoration: widget.checked
|
||||||
|
? TextDecoration.lineThrough
|
||||||
|
: TextDecoration.none),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
title: Text(widget.title,
|
title: Text(widget.title,
|
||||||
style: widget.checked
|
style: widget.checked
|
||||||
? const TextStyle(decoration: TextDecoration.lineThrough)
|
? const TextStyle(decoration: TextDecoration.lineThrough)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -10,15 +11,24 @@ import 'package:todoapp/modules/todowidget.dart';
|
|||||||
|
|
||||||
class TodoProvider extends ChangeNotifier {
|
class TodoProvider extends ChangeNotifier {
|
||||||
TodoProvider() {}
|
TodoProvider() {}
|
||||||
|
|
||||||
Future<void> readListsFromDisk() async {
|
Future<void> readListsFromDisk() async {
|
||||||
Map js = await FileHandler.fileContent;
|
Map js = await FileHandler.fileContent;
|
||||||
|
|
||||||
for (String key in js.keys) {
|
|
||||||
todoLists[key] = TodoList(title: key, widget: buildTodoListWidget(key), todos: []);
|
|
||||||
|
|
||||||
for (String key2 in js[key].keys) {
|
for (String key in js.keys) {
|
||||||
todoLists[key]!.todos.add(Todo(title: key2, widget: buildTodoWidget(key2, js[key][key2]), checked: js[key][key2]));
|
todoLists[key] =
|
||||||
|
TodoList(title: key, widget: buildTodoListWidget(key), todos: []);
|
||||||
|
|
||||||
|
Map decode = js[key];
|
||||||
|
for (var key2 in decode.keys) {
|
||||||
|
String title = key2;
|
||||||
|
bool checked = decode[key2]["checked"];
|
||||||
|
DateTime dueTime = DateTime.parse(decode[key2]["dueTime"]);
|
||||||
|
todoLists[key]!.todos.add(Todo(
|
||||||
|
title: title,
|
||||||
|
widget: buildTodoWidget(title, checked, dueTime),
|
||||||
|
checked: checked,
|
||||||
|
dueTime: dueTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,17 +89,17 @@ class TodoProvider extends ChangeNotifier {
|
|||||||
Map js = {};
|
Map js = {};
|
||||||
|
|
||||||
for (Todo t in todos) {
|
for (Todo t in todos) {
|
||||||
js[t.title] = t.checked;
|
js["${t.title}"] = {
|
||||||
|
"checked": t.checked,
|
||||||
|
"dueTime": t.dueTime.toString()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
print(js);
|
|
||||||
|
|
||||||
await FileHandler.saveList(js, selectedList);
|
await FileHandler.saveList(js, selectedList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTodo(String title) async {
|
void addTodo(String title, DateTime dueTime) async {
|
||||||
todos.add(Todo(
|
todos.add(Todo(
|
||||||
title: title, checked: false, widget: buildTodoWidget(title, false)));
|
title: title, checked: false, widget: buildTodoWidget(title, false, dueTime), dueTime: dueTime));
|
||||||
|
|
||||||
await writeTodoChanges();
|
await writeTodoChanges();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -103,10 +113,12 @@ class TodoProvider extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateTodo(String oldTitle, String newTitle) async {
|
void updateTodo(String oldTitle, String newTitle, DateTime dueTime) async {
|
||||||
Todo todo = todoByTitle(oldTitle);
|
Todo todo = todoByTitle(oldTitle);
|
||||||
todo.title = newTitle;
|
todo.title = newTitle;
|
||||||
todo.widget = buildTodoWidget(newTitle, todo.checked);
|
todo.dueTime = dueTime;
|
||||||
|
|
||||||
|
todo.widget = buildTodoWidget(newTitle, todo.checked, dueTime);
|
||||||
|
|
||||||
await writeTodoChanges();
|
await writeTodoChanges();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -116,7 +128,7 @@ class TodoProvider extends ChangeNotifier {
|
|||||||
Todo todo = todoByTitle(title);
|
Todo todo = todoByTitle(title);
|
||||||
|
|
||||||
todo.checked = checked;
|
todo.checked = checked;
|
||||||
todo.widget = buildTodoWidget(title, checked);
|
todo.widget = buildTodoWidget(title, checked, todo.dueTime);
|
||||||
|
|
||||||
await writeTodoChanges();
|
await writeTodoChanges();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -126,8 +138,8 @@ class TodoProvider extends ChangeNotifier {
|
|||||||
return TodoListWidget(title: title);
|
return TodoListWidget(title: title);
|
||||||
}
|
}
|
||||||
|
|
||||||
TodoWidget buildTodoWidget(String title, bool checked) {
|
TodoWidget buildTodoWidget(String title, bool checked, DateTime dueTime) {
|
||||||
return TodoWidget(checked: checked, title: title);
|
return TodoWidget(checked: checked, title: title, dueTime: dueTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
Todo todoByTitle(String title) {
|
Todo todoByTitle(String title) {
|
||||||
@@ -136,6 +148,10 @@ class TodoProvider extends ChangeNotifier {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Todo(title: "None", widget: const SizedBox(), checked: false);
|
return Todo(
|
||||||
|
title: "None",
|
||||||
|
widget: const SizedBox(),
|
||||||
|
checked: false,
|
||||||
|
dueTime: DateTime.now());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user