Initial commit
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
class FileHandler {
|
||||
|
||||
static Future<String> get localPath async {
|
||||
final directory = await getApplicationDocumentsDirectory();
|
||||
return directory.path;
|
||||
}
|
||||
|
||||
static Future<File> get localFile async {
|
||||
final path = await localPath;
|
||||
return File("$path/todos.json");
|
||||
}
|
||||
|
||||
static Future<dynamic> get fileContent async {
|
||||
await existCheck();
|
||||
File f = await localFile;
|
||||
String content = await f.readAsString();
|
||||
final js = await json.decode(content);
|
||||
return js;
|
||||
}
|
||||
|
||||
static Future<void> saveFile(js) async {
|
||||
File f = await localFile;
|
||||
String content = json.encode(js);
|
||||
f.writeAsString(content);
|
||||
}
|
||||
|
||||
static Future<void> saveList(js, String listName) async {
|
||||
final content = await fileContent;
|
||||
content[listName] = js;
|
||||
await saveFile(content);
|
||||
}
|
||||
|
||||
static Future<void> renameList(String oldListName, String newListName) async {
|
||||
var newJs = {};
|
||||
|
||||
final content = await fileContent;
|
||||
for (String key in content.keys) {
|
||||
if (key != oldListName) {
|
||||
newJs[key] = content[key];
|
||||
} else {
|
||||
newJs[newListName] = content[key];
|
||||
}
|
||||
}
|
||||
await saveFile(newJs);
|
||||
}
|
||||
|
||||
static Future<void> addList(String listName) async {
|
||||
var js = await fileContent;
|
||||
js[listName] = {};
|
||||
await saveFile(js);
|
||||
}
|
||||
|
||||
static Future<void> removeList(String listName) async {
|
||||
final js = await fileContent;
|
||||
var newJs = {};
|
||||
for (String key in js.keys) {
|
||||
if (key != listName) {
|
||||
newJs[key] = js[key];
|
||||
}
|
||||
}
|
||||
await saveFile(newJs);
|
||||
}
|
||||
|
||||
static Future<void> existCheck() async {
|
||||
File f = await localFile;
|
||||
bool exists = await f.exists();
|
||||
|
||||
if (!exists) {
|
||||
await saveFile({"Personal": {}});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Todo {
|
||||
Todo({required this.title, required this.widget, required this.checked});
|
||||
|
||||
String title;
|
||||
Widget widget;
|
||||
bool checked;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:todoapp/elems/todo.dart';
|
||||
|
||||
class TodoList {
|
||||
TodoList({required this.title, required this.widget, required this.todos});
|
||||
|
||||
String title;
|
||||
Widget widget;
|
||||
List<Todo> todos;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:todoapp/pages/Home.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (context) => TodoProvider())
|
||||
],
|
||||
child: MaterialApp(
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: Colors.blue, brightness: Brightness.dark),
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const Home(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/elems/todo.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
class AddListModal {
|
||||
static String tempValue = "";
|
||||
|
||||
static void add(BuildContext context) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
showDragHandle: true,
|
||||
useSafeArea: true,
|
||||
scrollControlDisabledMaxHeightRatio: 1,
|
||||
builder: (context) => 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>().addList(value);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
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>().addList(tempValue);
|
||||
}
|
||||
Navigator.pop(context);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/elems/todo.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
class AddTodoModal {
|
||||
static String tempValue = "";
|
||||
|
||||
static void add(BuildContext context) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
showDragHandle: true,
|
||||
useSafeArea: true,
|
||||
scrollControlDisabledMaxHeightRatio: 1,
|
||||
builder: (context) => 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);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
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>().addTodo(tempValue);
|
||||
}
|
||||
Navigator.pop(context);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/elems/todo.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
class EditListModal {
|
||||
static String tempValue = "";
|
||||
|
||||
static void add(BuildContext context, String title) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
showDragHandle: true,
|
||||
useSafeArea: true,
|
||||
scrollControlDisabledMaxHeightRatio: 1,
|
||||
builder: (context) => Padding(
|
||||
padding: const EdgeInsets.only(left: 30, right: 30),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
TextFormField(
|
||||
autofocus: true,
|
||||
initialValue: title,
|
||||
decoration: const InputDecoration(labelText: "Title"),
|
||||
onChanged: (value) => tempValue = value,
|
||||
onFieldSubmitted: (value) {
|
||||
context.read<TodoProvider>().renameList(title, value);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20,),
|
||||
SegmentedButton(
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
value: "Delete",
|
||||
label: Text("Delete"),
|
||||
icon: Icon(Icons.delete)
|
||||
),
|
||||
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>().renameList(title, tempValue);
|
||||
} else if (p0.last == "Delete") {
|
||||
context.read<TodoProvider>().removeList(title);
|
||||
}
|
||||
Navigator.pop(context);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/elems/todo.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
class EditTodoModal {
|
||||
static String tempValue = "";
|
||||
|
||||
static void add(BuildContext context, String title) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
showDragHandle: true,
|
||||
useSafeArea: true,
|
||||
scrollControlDisabledMaxHeightRatio: 1,
|
||||
builder: (context) => Padding(
|
||||
padding: const EdgeInsets.only(left: 30, right: 30),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
TextFormField(
|
||||
autofocus: true,
|
||||
initialValue: title,
|
||||
decoration: const InputDecoration(labelText: "Title"),
|
||||
onChanged: (value) => tempValue = value,
|
||||
onFieldSubmitted: (value) {
|
||||
context.read<TodoProvider>().updateTodo(title, value);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20,),
|
||||
SegmentedButton(
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
value: "Delete",
|
||||
label: Text("Delete"),
|
||||
icon: Icon(Icons.delete)
|
||||
),
|
||||
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(title, tempValue);
|
||||
} else if (p0.last == "Delete") {
|
||||
context.read<TodoProvider>().removeTodo(title);
|
||||
}
|
||||
Navigator.pop(context);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/modals/addtodomodal.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
class TodoActionButton extends StatelessWidget {
|
||||
const TodoActionButton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FloatingActionButton.extended(
|
||||
onPressed: () => {
|
||||
AddTodoModal.add(context)
|
||||
}, //TODO: implement
|
||||
label: const Text("Add ToDo"),
|
||||
icon: const Icon(Icons.add),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
class TodoAppBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
const TodoAppBar({super.key});
|
||||
|
||||
@override
|
||||
State<TodoAppBar> createState() => _TodoAppBarState();
|
||||
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
|
||||
}
|
||||
|
||||
class _TodoAppBarState extends State<TodoAppBar> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<TodoProvider>(
|
||||
builder: (context, todoProvider, child) => AppBar(
|
||||
elevation: 5,
|
||||
title: Text(todoProvider.selectedList),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
import '../elems/todo.dart';
|
||||
|
||||
class Body extends StatefulWidget {
|
||||
const Body({super.key});
|
||||
|
||||
@override
|
||||
State<Body> createState() => _BodyState();
|
||||
}
|
||||
|
||||
class _BodyState extends State<Body> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<TodoProvider>(
|
||||
builder: (context, todoProvider, child) => Column(
|
||||
children: [
|
||||
for (Todo t in context.read<TodoProvider>().todos) t.widget,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/modals/addlistmodal.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
class TodoDrawer extends StatefulWidget {
|
||||
const TodoDrawer({super.key});
|
||||
|
||||
@override
|
||||
State<TodoDrawer> createState() => _TodoDrawerState();
|
||||
}
|
||||
|
||||
class _TodoDrawerState extends State<TodoDrawer> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Drawer(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 20, right: 20),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 60),
|
||||
const Text("ToDo", style: TextStyle(fontSize: 20)),
|
||||
const SizedBox(height: 20),
|
||||
const Divider(height: 1),
|
||||
const SizedBox(height: 20),
|
||||
const Text("Lists", style: TextStyle(fontSize: 25)),
|
||||
const SizedBox(height: 10),
|
||||
SingleChildScrollView(
|
||||
child: Consumer<TodoProvider>(
|
||||
builder: (context, todoProvider, child) =>
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
for (String key in todoProvider.todoLists.keys)
|
||||
todoProvider.todoLists[key]!.widget,
|
||||
const SizedBox(height: 30),
|
||||
FilledButton.icon(
|
||||
onPressed: () {
|
||||
AddListModal.add(context);
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text("Add List"),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/modals/editlistmodal.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
class TodoListWidget extends StatefulWidget {
|
||||
const TodoListWidget({super.key, required this.title});
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<TodoListWidget> createState() => _TodoListWidgetState();
|
||||
}
|
||||
|
||||
class _TodoListWidgetState extends State<TodoListWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ButtonStyle buttonStyle = context
|
||||
.read<TodoProvider>()
|
||||
.selectedList == widget.title ? const ButtonStyle() : const ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll(Color(0x00000000)));
|
||||
|
||||
return FilledButton.tonal(
|
||||
onPressed: () {
|
||||
context.read<TodoProvider>().changeList(widget.title);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
onLongPress: () {
|
||||
EditListModal.add(context, widget.title);
|
||||
},
|
||||
style: buttonStyle,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
const Icon(Icons.list),
|
||||
const SizedBox(width: 10),
|
||||
Text(widget.title)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/modals/edittodomodal.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
class TodoWidget extends StatefulWidget {
|
||||
const TodoWidget({super.key, required this.checked, required this.title});
|
||||
|
||||
final bool checked;
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<TodoWidget> createState() => _TodoWidgetState();
|
||||
}
|
||||
|
||||
class _TodoWidgetState extends State<TodoWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onLongPress: () {
|
||||
EditTodoModal.add(context, widget.title);
|
||||
},
|
||||
child: CheckboxListTile(
|
||||
value: widget.checked,
|
||||
title: Text(widget.title,
|
||||
style: widget.checked
|
||||
? const TextStyle(decoration: TextDecoration.lineThrough)
|
||||
: const TextStyle()),
|
||||
onChanged: (value) =>
|
||||
{context.read<TodoProvider>().setTodoState(widget.title, value!)},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:todoapp/modules/actionbutton.dart';
|
||||
import 'package:todoapp/modules/appbar.dart';
|
||||
import 'package:todoapp/modules/body.dart';
|
||||
import 'package:todoapp/modules/drawer.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/providers/todoprovider.dart';
|
||||
|
||||
class Home extends StatefulWidget {
|
||||
const Home({super.key});
|
||||
|
||||
@override
|
||||
State<Home> createState() => _HomeState();
|
||||
}
|
||||
|
||||
class _HomeState extends State<Home> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder(
|
||||
future: context.read<TodoProvider>().readListsFromDisk(),
|
||||
builder: (context, snapshot) => const Scaffold(
|
||||
appBar: TodoAppBar(),
|
||||
body: Body(),
|
||||
drawer: TodoDrawer(),
|
||||
floatingActionButton: TodoActionButton(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:todoapp/elems/filehandler.dart';
|
||||
import 'package:todoapp/elems/todo.dart';
|
||||
import 'package:todoapp/elems/todolist.dart';
|
||||
import 'package:todoapp/modules/todolistwidget.dart';
|
||||
import 'package:todoapp/modules/todowidget.dart';
|
||||
|
||||
class TodoProvider extends ChangeNotifier {
|
||||
TodoProvider() {}
|
||||
|
||||
Future<void> readListsFromDisk() async {
|
||||
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) {
|
||||
todoLists[key]!.todos.add(Todo(title: key2, widget: buildTodoWidget(key2, js[key][key2]), checked: js[key][key2]));
|
||||
}
|
||||
}
|
||||
|
||||
todos = todoLists[selectedList]!.todos;
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Map<String, TodoList> todoLists = {};
|
||||
List<Todo> todos = [];
|
||||
String selectedList = "Personal";
|
||||
|
||||
void renameList(String oldTitle, String newTitle) async {
|
||||
TodoList tempList = todoLists[oldTitle]!;
|
||||
tempList.title = newTitle;
|
||||
tempList.widget = buildTodoListWidget(newTitle);
|
||||
todoLists.remove(oldTitle);
|
||||
todoLists[newTitle] = tempList;
|
||||
selectedList = newTitle;
|
||||
todos = todoLists[newTitle]!.todos;
|
||||
|
||||
await FileHandler.renameList(oldTitle, newTitle);
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void removeList(String title) async {
|
||||
todoLists.remove(title);
|
||||
selectedList = "Personal";
|
||||
todos = todoLists["Personal"]!.todos;
|
||||
|
||||
await FileHandler.removeList(title);
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void addList(String title) async {
|
||||
TodoList list =
|
||||
TodoList(title: title, widget: buildTodoListWidget(title), todos: []);
|
||||
todoLists[title] = list;
|
||||
|
||||
await FileHandler.addList(title);
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void changeList(String title) {
|
||||
if (!todoLists.containsKey(title)) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectedList = title;
|
||||
todos = todoLists[title]!.todos;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> writeTodoChanges() async {
|
||||
Map js = {};
|
||||
|
||||
for (Todo t in todos) {
|
||||
js[t.title] = t.checked;
|
||||
}
|
||||
|
||||
print(js);
|
||||
|
||||
await FileHandler.saveList(js, selectedList);
|
||||
}
|
||||
|
||||
void addTodo(String title) async {
|
||||
todos.add(Todo(
|
||||
title: title, checked: false, widget: buildTodoWidget(title, false)));
|
||||
|
||||
await writeTodoChanges();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void removeTodo(String title) async {
|
||||
Todo todo = todoByTitle(title);
|
||||
todos.remove(todo);
|
||||
|
||||
await writeTodoChanges();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void updateTodo(String oldTitle, String newTitle) async {
|
||||
Todo todo = todoByTitle(oldTitle);
|
||||
todo.title = newTitle;
|
||||
todo.widget = buildTodoWidget(newTitle, todo.checked);
|
||||
|
||||
await writeTodoChanges();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void setTodoState(String title, bool checked) async {
|
||||
Todo todo = todoByTitle(title);
|
||||
|
||||
todo.checked = checked;
|
||||
todo.widget = buildTodoWidget(title, checked);
|
||||
|
||||
await writeTodoChanges();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
TodoListWidget buildTodoListWidget(String title) {
|
||||
return TodoListWidget(title: title);
|
||||
}
|
||||
|
||||
TodoWidget buildTodoWidget(String title, bool checked) {
|
||||
return TodoWidget(checked: checked, title: title);
|
||||
}
|
||||
|
||||
Todo todoByTitle(String title) {
|
||||
for (Todo t in todos) {
|
||||
if (t.title == title) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return Todo(title: "None", widget: const SizedBox(), checked: false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user