Added undo snackbar for list deletion

Made all destinations show the menu instead of the back button (for now)
This commit is contained in:
Geoffroy Bonneville
2025-10-10 16:04:18 -04:00
parent c579a5d252
commit 6c9e5efe38
7 changed files with 43 additions and 16 deletions

View File

@@ -13,16 +13,16 @@ sealed class AppDestination(
object DueTodayList : AppDestination(
route = "todayList",
title = "Due Today",
showBackButton = true,
showBackButton = false,
)
object ManageLists : AppDestination(
route = "manageLists",
title = "Manage Lists",
showBackButton = true,
showBackButton = false,
)
object RecycleBin : AppDestination(
route = "recycleBin",
title = "Recycle Bin",
showBackButton = true,
showBackButton = false,
)
}

View File

@@ -6,7 +6,7 @@ import javax.inject.Inject
class DeleteTaskListUseCase@Inject constructor(
private val repository: TaskRepository
) {
suspend operator fun invoke(taskListId: Long) {
repository.deleteTaskList(taskListId, true)
suspend operator fun invoke(taskListId: Long, isDeleted: Boolean) {
repository.deleteTaskList(taskListId, isDeleted)
}
}

View File

@@ -6,10 +6,12 @@ import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@@ -62,6 +64,18 @@ fun ManageListsScreen(
showAddListSheet: () -> Unit
) {
var lists = viewModel.taskLists.toMutableList()
if (lists.isEmpty()) {
// Placeholder when no task lists exist
Box(
modifier = modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Tap + to create a new task list.")
}
return
}
val lazyListState = rememberLazyListState()
val reorderState = rememberReorderableLazyListState(
lazyListState = lazyListState,

View File

@@ -1,7 +1,7 @@
package com.wismna.geoffroy.donext.presentation.screen
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -12,8 +12,8 @@ import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.wismna.geoffroy.donext.presentation.viewmodel.TaskListViewModel
@@ -27,12 +27,11 @@ fun TaskListScreen(
if (tasks.isEmpty()) {
// Placeholder when recycle bin is empty
Column (
modifier = modifier.fillMaxSize().padding(10.dp),
Arrangement.Center
Box(
modifier = modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Nothing here!", modifier.fillMaxWidth(), textAlign = TextAlign.Center)
Text("Add tasks with the Create Task button", modifier.fillMaxWidth(), textAlign = TextAlign.Center)
Text("Tap + to create a new task.")
}
return
}

View File

@@ -59,7 +59,7 @@ class DueTodayViewModel @Inject constructor(
uiEventBus.send(
UiEvent.ShowUndoSnackbar(
message = "Task moved to trash",
message = "Task moved to recycle bin",
undoAction = {
viewModelScope.launch {
toggleTaskDeletedUseCase(taskId, false)

View File

@@ -11,6 +11,8 @@ import com.wismna.geoffroy.donext.domain.usecase.AddTaskListUseCase
import com.wismna.geoffroy.donext.domain.usecase.DeleteTaskListUseCase
import com.wismna.geoffroy.donext.domain.usecase.GetTaskListsUseCase
import com.wismna.geoffroy.donext.domain.usecase.UpdateTaskListUseCase
import com.wismna.geoffroy.donext.presentation.ui.events.UiEvent
import com.wismna.geoffroy.donext.presentation.ui.events.UiEventBus
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@@ -22,7 +24,8 @@ class ManageListsViewModel @Inject constructor(
getTaskListsUseCase: GetTaskListsUseCase,
private val addTaskListUseCase: AddTaskListUseCase,
private val updateTaskListUseCase: UpdateTaskListUseCase,
private val deleteTaskListUseCase: DeleteTaskListUseCase
private val deleteTaskListUseCase: DeleteTaskListUseCase,
private val uiEventBus: UiEventBus
) : ViewModel() {
var taskLists by mutableStateOf<List<TaskList>>(emptyList())
@@ -51,7 +54,18 @@ class ManageListsViewModel @Inject constructor(
}
fun deleteTaskList(taskListId: Long) {
viewModelScope.launch {
deleteTaskListUseCase(taskListId)
deleteTaskListUseCase(taskListId, true)
uiEventBus.send(
UiEvent.ShowUndoSnackbar(
message = "Task list moved to recycle bin",
undoAction = {
viewModelScope.launch {
deleteTaskListUseCase(taskListId, false)
}
}
)
)
}
}

View File

@@ -65,7 +65,7 @@ class TaskListViewModel @Inject constructor(
uiEventBus.send(
UiEvent.ShowUndoSnackbar(
message = "Task moved to trash",
message = "Task moved to recycle bin",
undoAction = {
viewModelScope.launch {
toggleTaskDeletedUseCase(taskId, false)