Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions lib/data/todo_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:todoapp/data/database/checklist_dao.dart';
import 'package:todoapp/data/database/task_dao.dart';
import 'package:todoapp/data/model/checklist.dart';
import 'package:todoapp/data/model/task.dart';
import 'package:todoapp/data/share_message_handler.dart';

abstract class TodoRepository {
Future<List<Task>> getTasks(int? checklistId);
Expand All @@ -28,16 +29,23 @@ abstract class TodoRepository {
required int taskId,
required String taskTitle,
});

Future<bool> share({
required String text,
required String title,
});
}

@Injectable(as: TodoRepository)
class TodoRepositoryImpl implements TodoRepository {
final TaskDAO _todoDAO;
final ChecklistDAO _checklistDAO;
final ShareMessageHandler _shareMessageHandler;

TodoRepositoryImpl(
this._todoDAO,
this._checklistDAO,
this._shareMessageHandler,
);

@override
Expand Down Expand Up @@ -97,4 +105,9 @@ class TodoRepositoryImpl implements TodoRepository {
Future<bool> updateTasks(List<Task> tasks, bool isCompletedNewValue) async {
return await _todoDAO.updateTasks(tasks, isCompletedNewValue);
}

@override
Future<bool> share({required String text, required String title}) {
return _shareMessageHandler.share(text: text, title: title);
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:injectable/injectable.dart';
import 'package:todoapp/data/model/task.dart';
import 'package:todoapp/data/model/tasks_complete_status.dart';
import 'package:todoapp/data/todo_repository.dart';
import 'package:todoapp/domain/task_list_sort_helper.dart';
import 'package:todoapp/domain/task_list_summary_helper.dart';
import 'package:todoapp/ui/components/widgets/task/taskslist/tasks_screen_state.dart';
import 'package:todoapp/util/share_message_handler.dart';
import 'package:todoapp/ui/components/tasks_view_model/tasks_screen_state.dart';

@Injectable()
class TasksViewModel extends Cubit<TasksScreenState> {
late TodoRepository _repository;
late ShareMessageHandler _shareMessageHandler;
late TaskListSummaryHelper _taskListSummaryHelper;
late TaskListSortHelper _taskListSortHelper;

TasksViewModel({
required TodoRepository repository,
required ShareMessageHandler shareMessageHandler,
required TaskListSummaryHelper taskListSummaryHelper,
required TaskListSortHelper taskListSortHelper,
}) : super(
Expand All @@ -28,7 +27,6 @@ class TasksViewModel extends Cubit<TasksScreenState> {
),
) {
_repository = repository;
_shareMessageHandler = shareMessageHandler;
_taskListSummaryHelper = taskListSummaryHelper;
_taskListSortHelper = taskListSortHelper;
}
Expand Down Expand Up @@ -79,7 +77,7 @@ class TasksViewModel extends Cubit<TasksScreenState> {
tasks: state.tasks,
);

await _shareMessageHandler.share(
await _repository.share(
text: checklist,
title: checklistName,
);
Expand Down
34 changes: 22 additions & 12 deletions lib/ui/components/widgets/check_all_action_chip_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:todoapp/data/model/tasks_complete_status.dart';
import 'package:todoapp/ui/l10n/app_localizations.dart';

class CheckAllActionChipWidget extends StatelessWidget {
final TasksCompleteStatus status;
final TasksCompleteStatus? status;
final VoidCallback onClick;

const CheckAllActionChipWidget({
Expand All @@ -17,17 +17,27 @@ class CheckAllActionChipWidget extends StatelessWidget {
final localizations = AppLocalizations.of(context)!;

String text;
switch (status) {
case TasksCompleteStatus.checkAll:
text = localizations.check_all;
case TasksCompleteStatus.uncheckAll:
text = localizations.uncheck_all;
if (status == null) {
return const SizedBox.shrink();
} else {
switch (status!) {
case TasksCompleteStatus.checkAll:
text = localizations.check_all;
case TasksCompleteStatus.uncheckAll:
text = localizations.uncheck_all;
}
return Padding(
padding: const EdgeInsets.only(
left: 12,
right: 12,
),
child: ActionChip(
label: Text(text),
onPressed: () {
onClick();
},
),
);
}
return ActionChip(
label: Text(text),
onPressed: () {
onClick();
},
);
}
}
21 changes: 12 additions & 9 deletions lib/ui/components/widgets/checklist/checklist_full_widget.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import 'package:flutter/material.dart';
import 'package:todoapp/data/model/checklist.dart';
import 'package:todoapp/data/model/task.dart';
import 'package:todoapp/data/model/tasks_complete_status.dart';
import 'package:todoapp/ui/components/remove_task_dialog_builder.dart';
import 'package:todoapp/ui/components/tasks_view_model/tasks_viewmodel.dart';
import 'package:todoapp/ui/components/widgets/checklist/checklist_item_widget.dart';
import 'package:todoapp/ui/components/widgets/task/taskslist/tasks_list_widget.dart';
import 'package:todoapp/ui/components/widgets/task/taskslist/tasks_viewmodel.dart';
import 'package:todoapp/ui/l10n/app_localizations.dart';
import 'package:todoapp/ui/todo_app_router_config.gr.dart';
import 'package:todoapp/util/di/dependency_startup_launcher.dart';
Expand All @@ -30,18 +31,15 @@ class ChecklistsListFullWidget extends StatefulWidget {
class ChecklistsListFullWidgetState extends State<ChecklistsListFullWidget> {
Checklist? selected;
List<Task>? tasks;
double progress = 0.0;
TasksCompleteStatus? status;
late TasksViewModel _tasksViewModel;

@override
void initState() {
super.initState();
final getIt = GetItStartupHandlerWrapper.getIt;
_tasksViewModel = TasksViewModel(
repository: getIt.get(),
taskListSummaryHelper: getIt.get(),
shareMessageHandler: getIt.get(),
taskListSortHelper: getIt.get(),
);
_tasksViewModel = getIt<TasksViewModel>();
}

@override
Expand All @@ -58,6 +56,8 @@ class ChecklistsListFullWidgetState extends State<ChecklistsListFullWidget> {
_tasksViewModel.stream.listen((state) {
setState(() {
tasks = state.tasks;
progress = state.progress;
status = state.tasksCompleteStatus;
});
});
});
Expand All @@ -84,7 +84,6 @@ class ChecklistsListFullWidgetState extends State<ChecklistsListFullWidget> {
}

Widget _buildTaskList(BuildContext context) {
final localizations = AppLocalizations.of(context)!;
return Row(
children: [
Expanded(
Expand All @@ -102,8 +101,9 @@ class ChecklistsListFullWidgetState extends State<ChecklistsListFullWidget> {
),
TasksListWidget(
flex: 6,
progress: progress,
status: status,
tasks: tasks == null ? [] : tasks!,
emptyTasksMessage: localizations.empty_tasks,
onCompleteTask: _tasksViewModel.onCompleteTask,
onRemoveTask: (task) => _showConfirmationDialogToRemoveTask(
context,
Expand All @@ -115,6 +115,9 @@ class ChecklistsListFullWidgetState extends State<ChecklistsListFullWidget> {
checklistId: selected?.id,
task: task,
),
onCompleteButtonAction: () {
_tasksViewModel.onCompleteButtonAction(selected?.id);
},
),
],
);
Expand Down
35 changes: 20 additions & 15 deletions lib/ui/components/widgets/progress_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,28 @@ class ProgressWidget extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
width: double.infinity,
height: containerHeight,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.onTertiary,
return Padding(
padding: const EdgeInsets.only(
bottom: 8,
),
child: Stack(
children: [
Container(
width: double.infinity,
height: containerHeight,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.onTertiary,
),
),
),
LayoutBuilder(
builder: (context, constraints) => _buildProgressBar(
progress: _progress,
maxWidth: constraints.maxWidth,
color: _color,
LayoutBuilder(
builder: (context, constraints) => _buildProgressBar(
progress: _progress,
maxWidth: constraints.maxWidth,
color: _color,
),
),
),
],
],
),
);
}

Expand Down
52 changes: 39 additions & 13 deletions lib/ui/components/widgets/task/taskslist/tasks_list_widget.dart
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
import 'package:flutter/material.dart';
import 'package:todoapp/data/model/task.dart';
import 'package:todoapp/data/model/tasks_complete_status.dart';
import 'package:todoapp/ui/components/widgets/check_all_action_chip_widget.dart';
import 'package:todoapp/ui/components/widgets/progress_widget.dart';
import 'package:todoapp/ui/components/widgets/task/task_cell_widget.dart';
import 'package:todoapp/ui/l10n/app_localizations.dart';

class TasksListWidget extends StatelessWidget {
final List<Task> tasks;
final double progress;
final TasksCompleteStatus? status;
final int? flex;
final String emptyTasksMessage;
final Function(Task) onRemoveTask;
final Function(Task p1, bool p2) onCompleteTask;
final Function(int oldIndex, int newIndex) onReorder;
final Function(Task) onTap;
final Function() onCompleteButtonAction;

const TasksListWidget({
super.key,
required this.tasks,
required this.progress,
this.status,
this.flex,
required this.emptyTasksMessage,
required this.onRemoveTask,
required this.onCompleteTask,
required this.onReorder,
required this.onTap,
required this.onCompleteButtonAction,
});

@override
Expand All @@ -28,26 +36,44 @@ class TasksListWidget extends StatelessWidget {
}

Widget _buildTaskList(BuildContext context) {
final localizations = AppLocalizations.of(context)!;
final emptyTaskMessage = localizations.empty_tasks;

Widget child;
if (tasks.isEmpty) {
child = Center(
child: Text(
emptyTasksMessage,
emptyTaskMessage,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyLarge,
),
);
} else {
child = ReorderableListView.builder(
onReorder: onReorder,
padding: const EdgeInsets.only(
top: 12,
bottom: 120,
),
itemBuilder: (context, index) => _buildTaskCellWidget(
tasks[index],
),
itemCount: tasks.length,
child = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ProgressWidget(
progress: progress,
),
CheckAllActionChipWidget(
status: status,
onClick: () {
onCompleteButtonAction();
},
),
Expanded(
child: ReorderableListView.builder(
onReorder: onReorder,
padding: const EdgeInsets.only(
bottom: 120.0,
),
itemBuilder: (context, index) => _buildTaskCellWidget(
tasks[index],
),
itemCount: tasks.length,
),
),
],
);
}

Expand Down
4 changes: 1 addition & 3 deletions lib/ui/screens/checklist/checklist_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ class ChecklistScreen extends StatelessWidget {

@override
Widget build(BuildContext context) {
final viewModel = ChecklistViewModel(
GetItStartupHandlerWrapper.getIt.get(),
);
final viewModel = GetItStartupHandlerWrapper.getIt<ChecklistViewModel>();

return ChecklistScreenScaffold(
formScreenValidator: GetItStartupHandlerWrapper.getIt.get(),
Expand Down
2 changes: 2 additions & 0 deletions lib/ui/screens/checklist/checklist_viewmodel.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import 'package:injectable/injectable.dart';
import 'package:todoapp/data/model/checklist.dart';

import 'package:todoapp/data/todo_repository.dart';

@Injectable()
class ChecklistViewModel {
late TodoRepository _repository;

Expand Down
9 changes: 3 additions & 6 deletions lib/ui/screens/checklists/checklists_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ class ChecklistsScreen extends StatelessWidget {

@override
Widget build(BuildContext context) {
final viewModel = ChecklistsViewModel(
GetItStartupHandlerWrapper.getIt.get(),
);
final viewModel =
GetItStartupHandlerWrapper.getIt.get<ChecklistsViewModel>();
viewModel.updateChecklists();

return BlocProvider(
Expand Down Expand Up @@ -71,9 +70,7 @@ class ChecklistsScaffold extends StatelessWidget {
onSharePressed: () async {
await _checklistFullKey.currentState?.onShareTasks();
},
onSortPressed: () => {
_checklistFullKey.currentState?.onSortTasks()
},
onSortPressed: () => {_checklistFullKey.currentState?.onSortTasks()},
onNewTaskPressed: () async {
/// Use key to access a specific internal behavior of
/// TaskViewModel to update the task list through
Expand Down
2 changes: 1 addition & 1 deletion lib/ui/screens/checklists/checklists_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'package:todoapp/data/todo_repository.dart';

import 'package:todoapp/ui/screens/checklists/checklists_screen_state.dart';

@injectable
@Injectable()
class ChecklistsViewModel extends Cubit<ChecklistsScreenState> {
late TodoRepository _repository;

Expand Down
Loading