@@ -38,51 +38,60 @@ class _HomeState extends ConsumerState<Home> {
3838 @override
3939 void initState () {
4040 super .initState ();
41- var todos = TodoRepository .fetchTodoList ();
41+ }
42+
43+ Future <void > onRefresh () {
44+ return ref.read (todoListProvider.notifier).fetchTodos ();
4245 }
4346
4447 @override
4548 Widget build (BuildContext context) {
49+ final AsyncValue <List <Todo >> todosProvider = ref.watch (todoListProvider); // this is only used for the loading animation
50+
4651 final todos = ref.watch (filteredTodos);
4752 final newTodoController = useTextEditingController ();
4853
4954 return GestureDetector (
50- onTap: () => FocusScope .of (context).unfocus (),
51- child: Scaffold (
52- body: ListView (
53- padding: const EdgeInsets .symmetric (horizontal: 20 , vertical: 40 ),
54- children: [
55- TextField (
56- key: addTodoKey,
57- controller: newTodoController,
58- decoration: const InputDecoration (
59- labelText: 'What do we need to do?' ,
60- ),
61- onSubmitted: (value) {
62- ref.read (todoListProvider.notifier).add (value);
63- newTodoController.clear ();
64- },
65- ),
66- const SizedBox (height: 42 ),
67- Padding (
68- padding: const EdgeInsets .only (bottom: 16.0 ),
69- child: Text ('${ref .watch (uncompletedTodosCount )} items left' , style: const TextStyle (fontSize: 20 )),
70- ),
71- if (todos.isNotEmpty) const Divider (height: 0 ),
72- for (var i = 0 ; i < todos.length; i++ ) ...[
73- if (i > 0 ) const Divider (height: 0 ),
74- ProviderScope (
75- overrides: [
76- _currentTodo.overrideWithValue (todos[i]),
77- ],
78- child: const TodoItem (),
79- ),
80- ],
81- ],
82- ),
83- bottomNavigationBar: const Menu (),
84- ),
85- );
55+ onTap: () => FocusScope .of (context).unfocus (),
56+ child: RefreshIndicator (
57+ onRefresh: onRefresh,
58+ child: Scaffold (
59+ body: todosProvider.when (
60+ loading: () => const Center (child: Center (child: CircularProgressIndicator ())),
61+ error: (error, stack) => const Text ('Oops, something unexpected happened' ),
62+ data: (_) => ListView (
63+ padding: const EdgeInsets .symmetric (horizontal: 20 , vertical: 40 ),
64+ children: [
65+ TextField (
66+ key: addTodoKey,
67+ controller: newTodoController,
68+ decoration: const InputDecoration (
69+ labelText: 'What do we need to do?' ,
70+ ),
71+ onSubmitted: (value) {
72+ ref.read (todoListProvider.notifier).add (value);
73+ newTodoController.clear ();
74+ },
75+ ),
76+ const SizedBox (height: 42 ),
77+ Padding (
78+ padding: const EdgeInsets .only (bottom: 16.0 ),
79+ child: Text ('${ref .watch (uncompletedTodosCount )} items left' , style: const TextStyle (fontSize: 20 )),
80+ ),
81+ if (todos.isNotEmpty) const Divider (height: 0 ),
82+ for (var i = 0 ; i < todos.length; i++ ) ...[
83+ if (i > 0 ) const Divider (height: 0 ),
84+ ProviderScope (
85+ overrides: [
86+ _currentTodo.overrideWithValue (todos[i]),
87+ ],
88+ child: const TodoItem (),
89+ ),
90+ ],
91+ ],
92+ )),
93+ bottomNavigationBar: const Menu (),
94+ )));
8695 }
8796}
8897
@@ -162,7 +171,6 @@ class TodoItem extends HookConsumerWidget {
162171 if (focused) {
163172 textEditingController.text = todo.description;
164173 } else {
165-
166174 // Only call for todo text change if a value is actually different
167175 if (todo.description != textEditingController.text) {
168176 // Commit changes only when the textfield is unfocused, for performance
0 commit comments