Implement Recycle Bin

Improve task items UI
This commit is contained in:
Geoffroy Bonneville
2025-09-24 12:33:11 -04:00
parent 1c28d9aacb
commit 2d4be63d81
17 changed files with 228 additions and 56 deletions

View File

@@ -13,6 +13,9 @@ interface TaskDao {
@Query("SELECT * FROM tasks WHERE task_list_id = :listId AND deleted = 0 ORDER BY done ASC, priority DESC") @Query("SELECT * FROM tasks WHERE task_list_id = :listId AND deleted = 0 ORDER BY done ASC, priority DESC")
fun getTasksForList(listId: Long): Flow<List<TaskEntity>> fun getTasksForList(listId: Long): Flow<List<TaskEntity>>
@Query("SELECT * FROM tasks WHERE deleted = 1")
suspend fun getDeletedTasks(): List<TaskEntity>
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertTask(task: TaskEntity) suspend fun insertTask(task: TaskEntity)
@@ -27,4 +30,7 @@ interface TaskDao {
@Query("UPDATE tasks SET deleted = :deleted WHERE task_list_id = :taskListId") @Query("UPDATE tasks SET deleted = :deleted WHERE task_list_id = :taskListId")
suspend fun toggleAllTasksFromListDeleted(taskListId: Long, deleted: Boolean) suspend fun toggleAllTasksFromListDeleted(taskListId: Long, deleted: Boolean)
@Query("DELETE FROM tasks WHERE id = :taskId")
suspend fun permanentDeleteTask(taskId: Long)
} }

View File

@@ -20,6 +20,10 @@ class TaskRepositoryImpl @Inject constructor(
return taskDao.getTasksForList(listId).map {entity -> entity.map { it.toDomain() }} return taskDao.getTasksForList(listId).map {entity -> entity.map { it.toDomain() }}
} }
override suspend fun getDeletedTasks(): List<Task> {
return taskDao.getDeletedTasks().map {entity -> entity.toDomain() }
}
override suspend fun insertTask(task: Task) { override suspend fun insertTask(task: Task) {
taskDao.insertTask(task.toEntity()) taskDao.insertTask(task.toEntity())
} }
@@ -28,7 +32,7 @@ class TaskRepositoryImpl @Inject constructor(
taskDao.updateTask(task.toEntity()) taskDao.updateTask(task.toEntity())
} }
override suspend fun deleteTask(taskId: Long, isDeleted: Boolean) { override suspend fun toggleTaskDeleted(taskId: Long, isDeleted: Boolean) {
taskDao.toggleTaskDeleted(taskId, isDeleted) taskDao.toggleTaskDeleted(taskId, isDeleted)
} }
@@ -36,6 +40,10 @@ class TaskRepositoryImpl @Inject constructor(
taskDao.toggleTaskDone(taskId, isDone) taskDao.toggleTaskDone(taskId, isDone)
} }
override suspend fun permanentlyDeleteTask(taskId: Long) {
taskDao.permanentDeleteTask(taskId)
}
override fun getTaskLists(): Flow<List<TaskList>> { override fun getTaskLists(): Flow<List<TaskList>> {
return taskListDao.getTaskLists().map {entities -> entities.map { it.toDomain() }} return taskListDao.getTaskLists().map {entities -> entities.map { it.toDomain() }}
} }

View File

@@ -15,4 +15,9 @@ sealed class AppDestination(
title = "Manage Lists", title = "Manage Lists",
showBackButton = true, showBackButton = true,
) )
object RecycleBin : AppDestination(
route = "recycleBin",
title = "Recycle Bin",
showBackButton = true,
)
} }

View File

@@ -7,10 +7,12 @@ import kotlinx.coroutines.flow.Flow
interface TaskRepository { interface TaskRepository {
fun getTasksForList(listId: Long): Flow<List<Task>> fun getTasksForList(listId: Long): Flow<List<Task>>
suspend fun getDeletedTasks(): List<Task>
suspend fun insertTask(task: Task) suspend fun insertTask(task: Task)
suspend fun updateTask(task: Task) suspend fun updateTask(task: Task)
suspend fun deleteTask(taskId: Long, isDeleted: Boolean) suspend fun toggleTaskDeleted(taskId: Long, isDeleted: Boolean)
suspend fun toggleTaskDone(taskId: Long, isDone: Boolean) suspend fun toggleTaskDone(taskId: Long, isDone: Boolean)
suspend fun permanentlyDeleteTask(taskId: Long)
fun getTaskLists(): Flow<List<TaskList>> fun getTaskLists(): Flow<List<TaskList>>
suspend fun insertTaskList(taskList: TaskList) suspend fun insertTaskList(taskList: TaskList)

View File

@@ -0,0 +1,9 @@
package com.wismna.geoffroy.donext.domain.usecase
import com.wismna.geoffroy.donext.domain.model.Task
import com.wismna.geoffroy.donext.domain.repository.TaskRepository
import javax.inject.Inject
class GetDeletedTasksUseCase @Inject constructor(private val repository: TaskRepository) {
suspend operator fun invoke(): List<Task> = repository.getDeletedTasks()
}

View File

@@ -3,10 +3,10 @@ package com.wismna.geoffroy.donext.domain.usecase
import com.wismna.geoffroy.donext.domain.repository.TaskRepository import com.wismna.geoffroy.donext.domain.repository.TaskRepository
import javax.inject.Inject import javax.inject.Inject
class DeleteTaskUseCase @Inject constructor( class PermanentlyDeleteTaskUseCase @Inject constructor(
private val repository: TaskRepository private val repository: TaskRepository
) { ) {
suspend operator fun invoke(taskId: Long) { suspend operator fun invoke(taskId: Long) {
repository.deleteTask(taskId, true) repository.permanentlyDeleteTask(taskId)
} }
} }

View File

@@ -0,0 +1,12 @@
package com.wismna.geoffroy.donext.domain.usecase
import com.wismna.geoffroy.donext.domain.repository.TaskRepository
import javax.inject.Inject
class ToggleTaskDeletedUseCase @Inject constructor(
private val repository: TaskRepository
) {
suspend operator fun invoke(taskId: Long, isDeleted: Boolean) {
repository.toggleTaskDeleted(taskId, isDeleted)
}
}

View File

@@ -84,9 +84,11 @@ fun MainScreen(
MenuScreen ( MenuScreen (
currentDestination = viewModel.currentDestination, currentDestination = viewModel.currentDestination,
onNavigate = { route -> onNavigate = { route ->
scope.launch { drawerState.close() } scope.launch {
navController.navigate(route) { drawerState.close()
restoreState = true navController.navigate(route) {
restoreState = true
}
} }
} }
) )
@@ -201,6 +203,12 @@ fun AppContent(
showAddListSheet = {viewModel.showAddListSheet = true} showAddListSheet = {viewModel.showAddListSheet = true}
) )
} }
composable(AppDestination.RecycleBin.route) {
RecycleBinScreen(
modifier = Modifier
)
}
} }
} }
} }

View File

@@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.List import androidx.compose.material.icons.filled.List
import androidx.compose.material3.Badge import androidx.compose.material3.Badge
@@ -70,6 +71,13 @@ fun MenuScreen(
Column { Column {
HorizontalDivider() HorizontalDivider()
NavigationDrawerItem(
label = { Text("Recycle Bin") },
icon = { Icon(Icons.Default.Delete, contentDescription = "Recycle Bin") },
selected = currentDestination is AppDestination.RecycleBin,
onClick = { onNavigate(AppDestination.RecycleBin.route) },
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
)
NavigationDrawerItem( NavigationDrawerItem(
label = { Text("Edit Lists") }, label = { Text("Edit Lists") },
icon = { Icon(Icons.Default.Edit, contentDescription = "Edit Lists") }, icon = { Icon(Icons.Default.Edit, contentDescription = "Edit Lists") },

View File

@@ -0,0 +1,65 @@
package com.wismna.geoffroy.donext.presentation.screen
import android.widget.Toast
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.wismna.geoffroy.donext.presentation.viewmodel.RecycleBinViewModel
import com.wismna.geoffroy.donext.presentation.viewmodel.TaskItemViewModel
@Composable
fun RecycleBinScreen(
modifier: Modifier = Modifier,
viewModel: RecycleBinViewModel = hiltViewModel(),
) {
val tasks = viewModel.deletedTasks
if (tasks.isEmpty()) {
// Placeholder when recycle bin is empty
Box(
modifier = modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Recycle Bin is empty")
}
} else {
val context = LocalContext.current
LazyColumn(
modifier = modifier.padding(8.dp)
) {
items(tasks, key = { it.id!! }) { task ->
Card(
//onClick = { onTaskClick(task) },
//elevation = CardDefaults.elevatedCardElevation(defaultElevation = 2.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceContainer,
),
) {
TaskItemScreen(
viewModel = TaskItemViewModel(task),
onSwipeLeft = {
viewModel.restore(task.id!!)
Toast.makeText(context, "Task restored", Toast.LENGTH_SHORT).show()
},
onSwipeRight = {
viewModel.deleteForever(task.id!!)
Toast.makeText(context, "Task deleted", Toast.LENGTH_SHORT).show()
}
)
}
}
}
}
}

View File

@@ -1,6 +1,5 @@
package com.wismna.geoffroy.donext.presentation.screen package com.wismna.geoffroy.donext.presentation.screen
import android.widget.Toast
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -28,12 +27,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.wismna.geoffroy.donext.domain.model.Priority import com.wismna.geoffroy.donext.domain.model.Priority
import com.wismna.geoffroy.donext.presentation.viewmodel.TaskItemViewModel import com.wismna.geoffroy.donext.presentation.viewmodel.TaskItemViewModel
@@ -41,23 +40,14 @@ import com.wismna.geoffroy.donext.presentation.viewmodel.TaskItemViewModel
fun TaskItemScreen( fun TaskItemScreen(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
viewModel: TaskItemViewModel, viewModel: TaskItemViewModel,
onSwipeDone: () -> Unit, onSwipeLeft: () -> Unit,
onSwipeDelete: () -> Unit onSwipeRight: () -> Unit
) { ) {
val context = LocalContext.current
val dismissState = rememberSwipeToDismissBoxState( val dismissState = rememberSwipeToDismissBoxState(
confirmValueChange = { confirmValueChange = {
when (it) { when (it) {
SwipeToDismissBoxValue.StartToEnd -> { SwipeToDismissBoxValue.StartToEnd -> { onSwipeRight() }
onSwipeDelete() SwipeToDismissBoxValue.EndToStart -> { onSwipeLeft() }
Toast.makeText(context, "Task deleted", Toast.LENGTH_SHORT).show()
}
SwipeToDismissBoxValue.EndToStart -> {
onSwipeDone()
Toast.makeText(context, "Task done", Toast.LENGTH_SHORT).show()
}
SwipeToDismissBoxValue.Settled -> return@rememberSwipeToDismissBoxState false SwipeToDismissBoxValue.Settled -> return@rememberSwipeToDismissBoxState false
} }
return@rememberSwipeToDismissBoxState true return@rememberSwipeToDismissBoxState true
@@ -101,6 +91,7 @@ fun TaskItemScreen(
// Title // Title
Text( Text(
text = viewModel.name, text = viewModel.name,
fontSize = 18.sp,
style = baseStyle, style = baseStyle,
modifier = Modifier modifier = Modifier
.align( .align(
@@ -134,13 +125,14 @@ fun TaskItemScreen(
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.height(40.dp) // 👈 adjust to the typical description height .height(40.dp)
.padding(top = 20.dp), .padding(top = 24.dp),
contentAlignment = Alignment.TopStart contentAlignment = Alignment.TopStart
) { ) {
if (!viewModel.description.isNullOrBlank()) { if (!viewModel.description.isNullOrBlank()) {
Text( Text(
text = viewModel.description, text = viewModel.description,
color = MaterialTheme.colorScheme.tertiary,
style = baseStyle.copy( style = baseStyle.copy(
fontSize = MaterialTheme.typography.bodyMedium.fontSize, fontSize = MaterialTheme.typography.bodyMedium.fontSize,
fontStyle = FontStyle.Italic fontStyle = FontStyle.Italic

View File

@@ -1,5 +1,6 @@
package com.wismna.geoffroy.donext.presentation.screen package com.wismna.geoffroy.donext.presentation.screen
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@@ -19,6 +20,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.wismna.geoffroy.donext.domain.model.Task import com.wismna.geoffroy.donext.domain.model.Task
@@ -38,6 +40,7 @@ fun TaskListScreen(
tasks.partition { !it.isDone } tasks.partition { !it.isDone }
} }
val context = LocalContext.current
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(8.dp), contentPadding = PaddingValues(8.dp),
@@ -58,11 +61,13 @@ fun TaskListScreen(
TaskItemScreen( TaskItemScreen(
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
viewModel = TaskItemViewModel(task), viewModel = TaskItemViewModel(task),
onSwipeDone = { onSwipeLeft = {
viewModel.updateTaskDone(task.id!!, true) viewModel.updateTaskDone(task.id!!, true)
Toast.makeText(context, "Task done", Toast.LENGTH_SHORT).show()
}, },
onSwipeDelete = { onSwipeRight = {
viewModel.deleteTask(task.id!!) viewModel.deleteTask(task.id!!)
Toast.makeText(context, "Task moved to recycle bin", Toast.LENGTH_SHORT).show()
} }
) )
} }
@@ -94,11 +99,13 @@ fun TaskListScreen(
TaskItemScreen( TaskItemScreen(
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
viewModel = TaskItemViewModel(task), viewModel = TaskItemViewModel(task),
onSwipeDone = { onSwipeLeft = {
viewModel.updateTaskDone(task.id!!, false) viewModel.updateTaskDone(task.id!!, false)
Toast.makeText(context, "Task done", Toast.LENGTH_SHORT).show()
}, },
onSwipeDelete = { onSwipeRight = {
viewModel.deleteTask(task.id!!) viewModel.deleteTask(task.id!!)
Toast.makeText(context, "Task moved to recycle bin", Toast.LENGTH_SHORT).show()
}, },
) )
} }

View File

@@ -25,48 +25,48 @@ fun DoNextTheme(
darkTheme -> darkColorScheme( darkTheme -> darkColorScheme(
primary = Purple40, primary = Purple40,
onPrimary = Color.White, onPrimary = LightSurfaceContainer,
primaryContainer = Purple40Container, primaryContainer = Purple40Container,
onPrimaryContainer = Color.White, onPrimaryContainer = LightSurfaceContainer,
secondary = PurpleGrey40, secondary = PurpleGrey40,
onSecondary = Color.White, onSecondary = LightSurfaceContainer,
secondaryContainer = PurpleGrey40Container, secondaryContainer = PurpleGrey40Container,
onSecondaryContainer = Color.White, onSecondaryContainer = LightSurfaceContainer,
tertiary = Pink40, tertiary = Pink80,
onTertiary = Color.White, onTertiary = DarkSurfaceContainer,
tertiaryContainer = Pink40Container, tertiaryContainer = Pink40Container,
onTertiaryContainer = Color.White, onTertiaryContainer = LightSurfaceContainer,
background = Color(0xFF121212), background = Color(0xFF121212),
onBackground = Color.White, onBackground = LightSurfaceContainer,
surface = Color(0xFF121212), surface = Color(0xFF121212),
onSurface = Color.White, onSurface = LightSurfaceContainer,
surfaceVariant = DarkSurfaceContainer, surfaceVariant = DarkSurfaceContainer,
onSurfaceVariant = Color.White, onSurfaceVariant = LightSurfaceContainer,
error = Color(0xFFCF6679), error = Color(0xFFCF6679),
onError = Color.Black onError = DarkSurfaceContainer
) )
else -> lightColorScheme( else -> lightColorScheme(
primary = Purple80, primary = Purple80,
onPrimary = Color.Black, onPrimary = DarkSurfaceContainer,
primaryContainer = Purple80Container, primaryContainer = Purple80Container,
onPrimaryContainer = Color.Black, onPrimaryContainer = DarkSurfaceContainer,
secondary = PurpleGrey80, secondary = PurpleGrey80,
onSecondary = Color.Black, onSecondary = DarkSurfaceContainer,
secondaryContainer = PurpleGrey80Container, secondaryContainer = PurpleGrey80Container,
onSecondaryContainer = Color.Black, onSecondaryContainer = DarkSurfaceContainer,
tertiary = Pink80, tertiary = Pink40,
onTertiary = Color.Black, onTertiary = LightSurfaceContainer,
tertiaryContainer = Pink80Container, tertiaryContainer = Pink80Container,
onTertiaryContainer = Color.Black, onTertiaryContainer = DarkSurfaceContainer,
background = Color(0xFFFFFBFE), background = Color(0xFFFFFBFE),
onBackground = Color.Black, onBackground = DarkSurfaceContainer,
surface = Color(0xFFFFFBFE), surface = Color(0xFFFFFBFE),
onSurface = Color.Black, onSurface = DarkSurfaceContainer,
surfaceVariant = LightSurfaceContainer, surfaceVariant = LightSurfaceContainer,
onSurfaceVariant = Color.Black, onSurfaceVariant = DarkSurfaceContainer,
error = Color(0xFFB00020), error = Color(0xFFB00020),
onError = Color.White onError = LightSurfaceContainer
) )
} }

View File

@@ -38,7 +38,7 @@ class MainViewModel @Inject constructor(
.onEach { lists -> .onEach { lists ->
destinations = lists.map { taskList -> destinations = lists.map { taskList ->
AppDestination.TaskList(taskList.id!!, taskList.name) AppDestination.TaskList(taskList.id!!, taskList.name)
} + AppDestination.ManageLists } + AppDestination.ManageLists + AppDestination.RecycleBin
isLoading = false isLoading = false
if (startDestination == AppDestination.ManageLists && destinations.isNotEmpty()) { if (startDestination == AppDestination.ManageLists && destinations.isNotEmpty()) {
startDestination = destinations.first() startDestination = destinations.first()

View File

@@ -0,0 +1,49 @@
package com.wismna.geoffroy.donext.presentation.viewmodel
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wismna.geoffroy.donext.domain.model.Task
import com.wismna.geoffroy.donext.domain.usecase.GetDeletedTasksUseCase
import com.wismna.geoffroy.donext.domain.usecase.PermanentlyDeleteTaskUseCase
import com.wismna.geoffroy.donext.domain.usecase.ToggleTaskDeletedUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class RecycleBinViewModel @Inject constructor(
private val getDeletedTasks: GetDeletedTasksUseCase,
private val restoreTask: ToggleTaskDeletedUseCase,
private val permanentlyDeleteTask: PermanentlyDeleteTaskUseCase
) : ViewModel() {
var deletedTasks by mutableStateOf<List<Task>>(emptyList())
private set
init {
loadDeletedTasks()
}
fun loadDeletedTasks() {
viewModelScope.launch {
deletedTasks = getDeletedTasks()
}
}
fun restore(taskId: Long) {
viewModelScope.launch {
restoreTask(taskId, false)
loadDeletedTasks()
}
}
fun deleteForever(taskId: Long) {
viewModelScope.launch {
permanentlyDeleteTask(taskId)
loadDeletedTasks()
}
}
}

View File

@@ -9,6 +9,7 @@ import androidx.lifecycle.viewModelScope
import com.wismna.geoffroy.donext.domain.model.Task import com.wismna.geoffroy.donext.domain.model.Task
import com.wismna.geoffroy.donext.domain.usecase.DeleteTaskListUseCase import com.wismna.geoffroy.donext.domain.usecase.DeleteTaskListUseCase
import com.wismna.geoffroy.donext.domain.usecase.GetTasksForListUseCase import com.wismna.geoffroy.donext.domain.usecase.GetTasksForListUseCase
import com.wismna.geoffroy.donext.domain.usecase.ToggleTaskDeletedUseCase
import com.wismna.geoffroy.donext.domain.usecase.ToggleTaskDoneUseCase import com.wismna.geoffroy.donext.domain.usecase.ToggleTaskDoneUseCase
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
@@ -20,7 +21,7 @@ import javax.inject.Inject
class TaskListViewModel @Inject constructor( class TaskListViewModel @Inject constructor(
getTasks: GetTasksForListUseCase, getTasks: GetTasksForListUseCase,
private val toggleTaskDoneUseCase: ToggleTaskDoneUseCase, private val toggleTaskDoneUseCase: ToggleTaskDoneUseCase,
private val deleteTaskListUseCase: DeleteTaskListUseCase, private val toggleTaskDeletedUseCase: ToggleTaskDeletedUseCase,
savedStateHandle: SavedStateHandle savedStateHandle: SavedStateHandle
) : ViewModel() { ) : ViewModel() {
@@ -47,7 +48,7 @@ class TaskListViewModel @Inject constructor(
} }
fun deleteTask(taskId: Long) { fun deleteTask(taskId: Long) {
viewModelScope.launch { viewModelScope.launch {
deleteTaskListUseCase(taskId) toggleTaskDeletedUseCase(taskId, true)
} }
} }
} }

View File

@@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope
import com.wismna.geoffroy.donext.domain.model.Priority import com.wismna.geoffroy.donext.domain.model.Priority
import com.wismna.geoffroy.donext.domain.model.Task import com.wismna.geoffroy.donext.domain.model.Task
import com.wismna.geoffroy.donext.domain.usecase.AddTaskUseCase import com.wismna.geoffroy.donext.domain.usecase.AddTaskUseCase
import com.wismna.geoffroy.donext.domain.usecase.DeleteTaskUseCase import com.wismna.geoffroy.donext.domain.usecase.ToggleTaskDeletedUseCase
import com.wismna.geoffroy.donext.domain.usecase.UpdateTaskUseCase import com.wismna.geoffroy.donext.domain.usecase.UpdateTaskUseCase
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -18,7 +18,7 @@ import javax.inject.Inject
class TaskViewModel @Inject constructor( class TaskViewModel @Inject constructor(
private val createTaskUseCase: AddTaskUseCase, private val createTaskUseCase: AddTaskUseCase,
private val updateTaskUseCase: UpdateTaskUseCase, private val updateTaskUseCase: UpdateTaskUseCase,
private val deleteTaskUseCase: DeleteTaskUseCase private val toggleTaskDeletedUseCase: ToggleTaskDeletedUseCase
) : ViewModel() { ) : ViewModel() {
var title by mutableStateOf("") var title by mutableStateOf("")
@@ -79,7 +79,7 @@ class TaskViewModel @Inject constructor(
fun delete() { fun delete() {
editingTaskId?.let { id -> editingTaskId?.let { id ->
viewModelScope.launch { viewModelScope.launch {
deleteTaskUseCase(id) toggleTaskDeletedUseCase(id, true)
reset() reset()
} }
} }