Skip to content

Commit cdfbbd0

Browse files
Merge branch 'sliverlist_inbox'
2 parents 5a5130f + 11927fb commit cdfbbd0

9 files changed

Lines changed: 142 additions & 5 deletions

File tree

.idea/libraries/Dart_Packages.xml

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/features/task/data/datasources/task_local_data_source.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ class TaskLocalDataSource {
4040
priority INTEGER,
4141
dueDate TEXT,
4242
timeSelected INTEGER,
43-
dateSelected INTEGER
43+
dateSelected INTEGER,
44+
position INTEGER
4445
)
4546
''');
4647
}
@@ -65,6 +66,7 @@ class TaskLocalDataSource {
6566
'dueDate': task.dueDate?.toString(),
6667
'timeSelected': task.timeSelected ? 1 : 0,
6768
'dateSelected': task.dateSelected ? 1 : 0,
69+
'position': task.position,
6870
},
6971
conflictAlgorithm: ConflictAlgorithm.replace,
7072
);
@@ -87,6 +89,7 @@ class TaskLocalDataSource {
8789
'dueDate': task.dueDate?.toString(),
8890
'timeSelected': task.timeSelected ? 1 : 0,
8991
'dateSelected': task.dateSelected ? 1 : 0,
92+
'position': task.position,
9093
},
9194
conflictAlgorithm: ConflictAlgorithm.replace,
9295
);
@@ -125,6 +128,7 @@ class TaskLocalDataSource {
125128
'dueDate': task.dueDate?.toString(),
126129
'timeSelected': task.timeSelected ? 1 : 0,
127130
'dateSelected': task.dateSelected ? 1 : 0,
131+
'position': task.position,
128132
},
129133
where: 'id = ?',
130134
whereArgs: [task.id],
@@ -215,6 +219,7 @@ class TaskLocalDataSource {
215219
dueDate: parsedDueDate,
216220
timeSelected: map['timeSelected'] == 1,
217221
dateSelected: map['dateSelected'] == 1,
222+
position: map['position'] ?? 0,
218223
);
219224
}
220225
}

lib/features/task/domain/entities/task.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class Task {
77
DateTime? dueDate;
88
bool timeSelected;
99
bool dateSelected;
10+
int position;
1011

1112
Task({
1213
String? id,
@@ -17,6 +18,7 @@ class Task {
1718
this.dueDate,
1819
this.timeSelected = false,
1920
this.dateSelected = false,
21+
this.position = 0,
2022
}) : id = id ?? DateTime.now().toString();
2123

2224
// copyWith method
@@ -29,6 +31,7 @@ class Task {
2931
DateTime? dueDate,
3032
bool? timeSelected,
3133
bool? dateSelected,
34+
int? position,
3235
}) {
3336
return Task(
3437
id: id ?? this.id,
@@ -39,6 +42,7 @@ class Task {
3942
dueDate: dueDate ?? this.dueDate,
4043
timeSelected: this.timeSelected,
4144
dateSelected: this.dateSelected,
45+
position: position ?? this.position,
4246
);
4347
}
4448

lib/features/task/presentation/pages/inbox_page.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import 'package:provider/provider.dart';
33
import 'package:butter_task/features/task/presentation/providers/task_provider.dart';
44
import 'package:butter_task/features/task/presentation/widgets/task_list.dart';
55
import 'package:butter_task/features/task/domain/entities/task.dart';
6-
import 'package:butter_task/features/task/presentation/widgets/task_form.dart'; // Make sure this import is correct
6+
import 'package:butter_task/features/task/presentation/widgets/task_form.dart';
7+
8+
import '../widgets/task_sliver_list.dart'; // Make sure this import is correct
79

810
class InboxPage extends StatefulWidget {
911
const InboxPage({super.key});
@@ -97,7 +99,7 @@ class _InboxPageState extends State<InboxPage> {
9799
Expanded(
98100
child: Consumer<TaskProvider>(
99101
builder: (context, taskProvider, child) {
100-
return TaskList(key: UniqueKey());
102+
return TaskSliverList(key: UniqueKey());
101103
},
102104
),
103105
),

lib/features/task/presentation/providers/task_provider.dart

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class TaskProvider with ChangeNotifier {
1919

2020
// Update the tasks list
2121
_tasks = fetchedTasks;
22-
22+
_tasks.sort((a, b) => a.position.compareTo(b.position));
2323
// Notify listeners that the state has changed
2424
notifyListeners();
2525
} catch (e) {
@@ -31,6 +31,7 @@ class TaskProvider with ChangeNotifier {
3131
// Method to add a new task
3232
Future<void> addTask(Task task) async {
3333
try {
34+
task.position = _tasks.length;
3435
// Call repository to add task
3536
final addedTask = await _repository.addTask(task);
3637

@@ -70,4 +71,16 @@ class TaskProvider with ChangeNotifier {
7071
notifyListeners();
7172
}
7273
}
74+
75+
void updateTaskOrder(List<Task> updatedTasks) {
76+
for (Task task in tasks) {
77+
task.position = updatedTasks.indexOf(task);
78+
}
79+
//sort tasks by position
80+
_tasks.sort((a, b) => a.position.compareTo(b.position));
81+
for (Task task in _tasks) {
82+
_repository.updateTask(task);
83+
}
84+
notifyListeners();
85+
}
7386
}

lib/features/task/presentation/widgets/task_form.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ class _TaskFormState extends State<TaskForm> {
233233
dueDate: selectedDate,
234234
timeSelected: timeSelected,
235235
dateSelected: dateSelected,
236+
position: widget.existingTask?.position ?? 0,
236237
);
237238
// Return the task to the previous screen
238239
Navigator.pop(context, task);
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:provider/provider.dart';
3+
import 'package:butter_task/features/task/presentation/providers/task_provider.dart';
4+
import 'package:butter_task/features/task/presentation/widgets/task_item_widget.dart';
5+
import 'package:butter_task/features/task/domain/entities/task.dart';
6+
7+
class TaskSliverList extends StatefulWidget {
8+
const TaskSliverList({super.key});
9+
10+
@override
11+
State<TaskSliverList> createState() => _TaskSliverListState();
12+
}
13+
14+
class _TaskSliverListState extends State<TaskSliverList> {
15+
late List<Task> tasks;
16+
17+
@override
18+
void initState() {
19+
super.initState();
20+
tasks = [];
21+
}
22+
23+
@override
24+
void didChangeDependencies() {
25+
super.didChangeDependencies();
26+
final taskProvider = Provider.of<TaskProvider>(context);
27+
setState(() {
28+
tasks = taskProvider.selectedTasks;
29+
});
30+
}
31+
32+
void _deleteTask(Task task) {
33+
final taskProvider = Provider.of<TaskProvider>(context, listen: false);
34+
taskProvider.removeTask(task);
35+
}
36+
37+
void _updateTaskOrder(List<Task> updatedTasks) {
38+
final taskProvider = Provider.of<TaskProvider>(context, listen: false);
39+
taskProvider.updateTaskOrder(updatedTasks);
40+
}
41+
42+
@override
43+
Widget build(BuildContext context) {
44+
return tasks.isEmpty
45+
? Center(
46+
child: Text(
47+
Provider.of<TaskProvider>(context).showDoneTasks
48+
? 'No tasks already done.'
49+
: 'No tasks yet. Add a task!',
50+
style: Theme.of(context).textTheme.titleMedium,
51+
),
52+
)
53+
: ReorderableListView.builder(
54+
itemCount: tasks.length,
55+
itemBuilder: (BuildContext context, int index) {
56+
return Dismissible(
57+
key: Key(tasks[index].id.toString()),
58+
direction: DismissDirection.startToEnd,
59+
background: Container(
60+
color: Colors.red,
61+
alignment: Alignment.centerLeft,
62+
padding: const EdgeInsets.symmetric(horizontal: 20),
63+
child: const Icon(Icons.delete, color: Colors.white),
64+
),
65+
onDismissed: (direction) {
66+
_deleteTask(tasks[index]);
67+
},
68+
child: TaskItem(task: tasks[index]),
69+
);
70+
},
71+
onReorder: (int oldIndex, int newIndex) {
72+
setState(() {
73+
if (oldIndex < newIndex) {
74+
newIndex -= 1;
75+
}
76+
final Task removedTask = tasks.removeAt(oldIndex);
77+
tasks.insert(newIndex, removedTask);
78+
79+
// Update task order in the provider
80+
_updateTaskOrder(tasks);
81+
});
82+
},
83+
);
84+
}
85+
}

lib/main.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import 'dart:io' show Platform;
12
import 'package:flutter/material.dart';
23
import 'package:provider/provider.dart';
4+
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
35
import 'package:butter_task/features/task/presentation/providers/task_provider.dart';
46
import 'package:butter_task/features/task/presentation/pages/inbox_page.dart';
57
import 'package:butter_task/features/task/domain/repositories/task_repository.dart';
@@ -8,6 +10,14 @@ import 'package:butter_task/features/task/data/datasources/task_local_data_sourc
810
import 'package:butter_task/features/task/data/datasources/task_remote_data_source.dart';
911

1012
void main() {
13+
// Initialize SQLite for desktop/non-mobile platforms
14+
if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
15+
// Initialize FFI
16+
sqfliteFfiInit();
17+
// Set the database factory to the FFI implementation
18+
databaseFactory = databaseFactoryFfi;
19+
}
20+
1121
// Create the dependencies
1222
final TaskLocalDataSource localDataSource = TaskLocalDataSource();
1323
final TaskRemoteDataSource remoteDataSource = TaskRemoteDataSourceImpl();
@@ -46,4 +56,4 @@ class MyApp extends StatelessWidget {
4656
home: const InboxPage(),
4757
);
4858
}
49-
}
59+
}

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ dependencies:
3232
sdk: flutter
3333
provider: ^6.1.2
3434
uuid: ^4.3.3
35+
sqflite_common_ffi: ^2.0.0
3536

3637
# The following adds the Cupertino Icons font to your application.
3738
# Use with the CupertinoIcons class for iOS style icons.

0 commit comments

Comments
 (0)