mirror of
https://github.com/wismna/DoNext.git
synced 2025-10-03 07:30:13 -04:00
Added swiping moves to the tasks: left for done, right for delete
Rename some DAO functions
This commit is contained in:
@@ -20,11 +20,11 @@ interface TaskDao {
|
|||||||
suspend fun updateTask(task: TaskEntity)
|
suspend fun updateTask(task: TaskEntity)
|
||||||
|
|
||||||
@Query("UPDATE tasks SET done = :done WHERE id = :taskId")
|
@Query("UPDATE tasks SET done = :done WHERE id = :taskId")
|
||||||
suspend fun markTaskDone(taskId: Long, done: Boolean)
|
suspend fun toggleTaskDone(taskId: Long, done: Boolean)
|
||||||
|
|
||||||
@Query("UPDATE tasks SET deleted = :deleted WHERE id = :taskId")
|
@Query("UPDATE tasks SET deleted = :deleted WHERE id = :taskId")
|
||||||
suspend fun markTaskDeleted(taskId: Long, deleted: Boolean)
|
suspend fun toggleTaskDeleted(taskId: Long, deleted: Boolean)
|
||||||
|
|
||||||
@Query("UPDATE tasks SET deleted = :deleted WHERE task_list_id = :taskListId")
|
@Query("UPDATE tasks SET deleted = :deleted WHERE task_list_id = :taskListId")
|
||||||
suspend fun deleteAllTasksFromList(taskListId: Long, deleted: Boolean)
|
suspend fun toggleAllTasksFromListDeleted(taskListId: Long, deleted: Boolean)
|
||||||
}
|
}
|
@@ -29,11 +29,11 @@ class TaskRepositoryImpl @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteTask(taskId: Long, isDeleted: Boolean) {
|
override suspend fun deleteTask(taskId: Long, isDeleted: Boolean) {
|
||||||
taskDao.markTaskDeleted(taskId, isDeleted)
|
taskDao.toggleTaskDeleted(taskId, isDeleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun toggleTaskDone(taskId: Long, isDone: Boolean) {
|
override suspend fun toggleTaskDone(taskId: Long, isDone: Boolean) {
|
||||||
taskDao.markTaskDone(taskId, isDone)
|
taskDao.toggleTaskDone(taskId, isDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTaskLists(): Flow<List<TaskList>> {
|
override fun getTaskLists(): Flow<List<TaskList>> {
|
||||||
@@ -49,7 +49,7 @@ class TaskRepositoryImpl @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteTaskList(taskListId: Long, isDeleted: Boolean) {
|
override suspend fun deleteTaskList(taskListId: Long, isDeleted: Boolean) {
|
||||||
taskDao.deleteAllTasksFromList(taskListId, isDeleted)
|
taskDao.toggleAllTasksFromListDeleted(taskListId, isDeleted)
|
||||||
taskListDao.deleteTaskList(taskListId, isDeleted)
|
taskListDao.deleteTaskList(taskListId, isDeleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,6 +7,7 @@ import androidx.compose.animation.togetherWith
|
|||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@@ -45,6 +46,7 @@ import androidx.compose.ui.focus.focusRequester
|
|||||||
import androidx.compose.ui.semantics.CustomAccessibilityAction
|
import androidx.compose.ui.semantics.CustomAccessibilityAction
|
||||||
import androidx.compose.ui.semantics.clearAndSetSemantics
|
import androidx.compose.ui.semantics.clearAndSetSemantics
|
||||||
import androidx.compose.ui.semantics.customActions
|
import androidx.compose.ui.semantics.customActions
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
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.presentation.viewmodel.ManageListsViewModel
|
import com.wismna.geoffroy.donext.presentation.viewmodel.ManageListsViewModel
|
||||||
@@ -67,7 +69,12 @@ fun ManageListsScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
LazyColumn(modifier = modifier.fillMaxWidth().padding(), state = lazyListState) {
|
LazyColumn(
|
||||||
|
modifier = modifier.fillMaxWidth(),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
contentPadding = PaddingValues(vertical = 8.dp),
|
||||||
|
state = lazyListState
|
||||||
|
) {
|
||||||
itemsIndexed(lists, key = { _, list -> list.id!! }) { index, list ->
|
itemsIndexed(lists, key = { _, list -> list.id!! }) { index, list ->
|
||||||
|
|
||||||
var isInEditMode by remember { mutableStateOf(false) }
|
var isInEditMode by remember { mutableStateOf(false) }
|
||||||
@@ -81,7 +88,7 @@ fun ManageListsScreen(
|
|||||||
onClick = {},
|
onClick = {},
|
||||||
elevation = CardDefaults.elevatedCardElevation(defaultElevation = 5.dp),
|
elevation = CardDefaults.elevatedCardElevation(defaultElevation = 5.dp),
|
||||||
colors = CardDefaults.cardColors(
|
colors = CardDefaults.cardColors(
|
||||||
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
|
containerColor = MaterialTheme.colorScheme.secondaryContainer,
|
||||||
),
|
),
|
||||||
modifier = Modifier.draggableHandle(
|
modifier = Modifier.draggableHandle(
|
||||||
onDragStopped = {
|
onDragStopped = {
|
||||||
@@ -127,8 +134,8 @@ fun ManageListsScreen(
|
|||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
AnimatedContent(
|
AnimatedContent(
|
||||||
//modifier = Modifier.padding(start = 12.dp),
|
|
||||||
targetState = isInEditMode,
|
targetState = isInEditMode,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
transitionSpec = {
|
transitionSpec = {
|
||||||
fadeIn() togetherWith fadeOut()
|
fadeIn() togetherWith fadeOut()
|
||||||
},
|
},
|
||||||
@@ -141,7 +148,12 @@ fun ManageListsScreen(
|
|||||||
singleLine = true
|
singleLine = true
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Text(list.name)
|
Text(
|
||||||
|
modifier = Modifier.padding(start = 8.dp),
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
maxLines = 1,
|
||||||
|
text = list.name
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnimatedContent(
|
AnimatedContent(
|
||||||
|
@@ -17,6 +17,7 @@ import androidx.compose.material3.NavigationDrawerItemDefaults
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
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.AppDestination
|
import com.wismna.geoffroy.donext.domain.model.AppDestination
|
||||||
@@ -46,7 +47,13 @@ fun MenuScreen(
|
|||||||
)
|
)
|
||||||
viewModel.taskLists.forEach { list ->
|
viewModel.taskLists.forEach { list ->
|
||||||
NavigationDrawerItem(
|
NavigationDrawerItem(
|
||||||
label = { Text(list.name) },
|
label = {
|
||||||
|
Text(
|
||||||
|
text = list.name,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
},
|
||||||
icon = { Icon(Icons.Default.List, contentDescription = list.name) },
|
icon = { Icon(Icons.Default.List, contentDescription = list.name) },
|
||||||
selected = currentDestination is AppDestination.TaskList &&
|
selected = currentDestination is AppDestination.TaskList &&
|
||||||
currentDestination.taskListId == list.id,
|
currentDestination.taskListId == list.id,
|
||||||
|
@@ -1,29 +1,35 @@
|
|||||||
package com.wismna.geoffroy.donext.presentation.screen
|
package com.wismna.geoffroy.donext.presentation.screen
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import android.widget.Toast
|
||||||
import androidx.compose.animation.expandVertically
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.animation.fadeOut
|
|
||||||
import androidx.compose.animation.shrinkVertically
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.IntrinsicSize
|
import androidx.compose.foundation.layout.IntrinsicSize
|
||||||
import androidx.compose.foundation.layout.Row
|
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.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.material.icons.filled.Close
|
||||||
|
import androidx.compose.material.icons.filled.Delete
|
||||||
|
import androidx.compose.material.icons.filled.Done
|
||||||
import androidx.compose.material3.Badge
|
import androidx.compose.material3.Badge
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.SwipeToDismissBox
|
||||||
|
import androidx.compose.material3.SwipeToDismissBoxState
|
||||||
|
import androidx.compose.material3.SwipeToDismissBoxValue
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.rememberSwipeToDismissBoxState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
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.draw.clip
|
|
||||||
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.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
|
||||||
@@ -35,9 +41,30 @@ import com.wismna.geoffroy.donext.presentation.viewmodel.TaskItemViewModel
|
|||||||
fun TaskItemScreen(
|
fun TaskItemScreen(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
viewModel: TaskItemViewModel,
|
viewModel: TaskItemViewModel,
|
||||||
onClick: () -> Unit,
|
onSwipeDone: () -> Unit,
|
||||||
onToggleDone: (Boolean) -> Unit
|
onSwipeDelete: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val dismissState = rememberSwipeToDismissBoxState(
|
||||||
|
confirmValueChange = {
|
||||||
|
when (it) {
|
||||||
|
SwipeToDismissBoxValue.StartToEnd -> {
|
||||||
|
onSwipeDelete()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
return@rememberSwipeToDismissBoxState true
|
||||||
|
},
|
||||||
|
// positional threshold of 25%
|
||||||
|
positionalThreshold = { it * .25f }
|
||||||
|
)
|
||||||
val baseStyle = MaterialTheme.typography.bodyLarge.copy(
|
val baseStyle = MaterialTheme.typography.bodyLarge.copy(
|
||||||
fontWeight = when (viewModel.priority) {
|
fontWeight = when (viewModel.priority) {
|
||||||
Priority.HIGH -> FontWeight.Bold
|
Priority.HIGH -> FontWeight.Bold
|
||||||
@@ -49,25 +76,22 @@ fun TaskItemScreen(
|
|||||||
Priority.NORMAL -> MaterialTheme.colorScheme.onSurface
|
Priority.NORMAL -> MaterialTheme.colorScheme.onSurface
|
||||||
Priority.LOW -> MaterialTheme.colorScheme.onSurfaceVariant
|
Priority.LOW -> MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
},
|
},
|
||||||
textDecoration = if (viewModel.isDone) TextDecoration.LineThrough else TextDecoration.None)
|
textDecoration = if (viewModel.isDone) TextDecoration.LineThrough else TextDecoration.None
|
||||||
|
)
|
||||||
|
|
||||||
|
SwipeToDismissBox(
|
||||||
|
state = dismissState,
|
||||||
|
modifier = modifier,
|
||||||
|
backgroundContent = { DismissBackground(dismissState, viewModel.isDone) },
|
||||||
|
content = {
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable { onClick() }
|
.background(MaterialTheme.colorScheme.surfaceContainer)
|
||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
.alpha(if (viewModel.isDone || viewModel.priority == Priority.LOW) 0.5f else 1f),
|
.alpha(if (viewModel.isDone || viewModel.priority == Priority.LOW) 0.5f else 1f),
|
||||||
verticalAlignment = Alignment.CenterVertically // centers checkbox + content
|
verticalAlignment = Alignment.CenterVertically // centers checkbox + content
|
||||||
) {
|
) {
|
||||||
// Done checkbox
|
|
||||||
Checkbox(
|
|
||||||
checked = viewModel.isDone,
|
|
||||||
onCheckedChange = onToggleDone,
|
|
||||||
modifier = Modifier
|
|
||||||
.size(40.dp)
|
|
||||||
.clip(CircleShape)
|
|
||||||
)
|
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
@@ -82,7 +106,9 @@ fun TaskItemScreen(
|
|||||||
.align(
|
.align(
|
||||||
if (viewModel.description.isNullOrBlank()) Alignment.CenterStart
|
if (viewModel.description.isNullOrBlank()) Alignment.CenterStart
|
||||||
else Alignment.TopStart
|
else Alignment.TopStart
|
||||||
)
|
),
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
maxLines = 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Due date badge
|
// Due date badge
|
||||||
@@ -105,23 +131,56 @@ fun TaskItemScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Optional description
|
// Optional description
|
||||||
this@Row.AnimatedVisibility(
|
Box(
|
||||||
visible = !viewModel.description.isNullOrBlank(),
|
|
||||||
modifier = Modifier.align(Alignment.BottomStart),
|
|
||||||
enter = fadeIn() + expandVertically(),
|
|
||||||
exit = fadeOut() + shrinkVertically()
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = viewModel.description!!,
|
|
||||||
style = baseStyle.copy(fontSize = MaterialTheme.typography.bodyMedium.fontSize),
|
|
||||||
maxLines = 3,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.BottomStart)
|
.fillMaxWidth()
|
||||||
.padding(top = 20.dp) // spacing below title
|
.height(40.dp) // 👈 adjust to the typical description height
|
||||||
|
.padding(top = 20.dp),
|
||||||
|
contentAlignment = Alignment.TopStart
|
||||||
|
) {
|
||||||
|
if (!viewModel.description.isNullOrBlank()) {
|
||||||
|
Text(
|
||||||
|
text = viewModel.description,
|
||||||
|
style = baseStyle.copy(
|
||||||
|
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
|
||||||
|
fontStyle = FontStyle.Italic
|
||||||
|
),
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DismissBackground(dismissState: SwipeToDismissBoxState, isDone: Boolean) {
|
||||||
|
val color = when (dismissState.dismissDirection) {
|
||||||
|
SwipeToDismissBoxValue.StartToEnd -> MaterialTheme.colorScheme.error
|
||||||
|
SwipeToDismissBoxValue.EndToStart -> Color(0xFF18590D)
|
||||||
|
SwipeToDismissBoxValue.Settled -> Color.Transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(color)
|
||||||
|
.padding(12.dp, 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Delete,
|
||||||
|
tint = Color.LightGray,
|
||||||
|
contentDescription = "Delete"
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier)
|
||||||
|
Icon(
|
||||||
|
if (isDone) Icons.Default.Close else Icons.Default.Done,
|
||||||
|
tint = Color.LightGray,
|
||||||
|
contentDescription = "Archive"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
@@ -9,9 +9,12 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Add
|
import androidx.compose.material.icons.filled.Add
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
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
|
||||||
@@ -45,15 +48,25 @@ fun TaskListScreen(
|
|||||||
items = active,
|
items = active,
|
||||||
key = { it.id!! }
|
key = { it.id!! }
|
||||||
) { task ->
|
) { task ->
|
||||||
|
Card(
|
||||||
|
onClick = { onTaskClick(task) },
|
||||||
|
//elevation = CardDefaults.elevatedCardElevation(defaultElevation = 2.dp),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
||||||
|
),
|
||||||
|
) {
|
||||||
TaskItemScreen(
|
TaskItemScreen(
|
||||||
modifier = Modifier.animateItem(),
|
modifier = Modifier.animateItem(),
|
||||||
viewModel = TaskItemViewModel(task),
|
viewModel = TaskItemViewModel(task),
|
||||||
onClick = { onTaskClick(task) },
|
onSwipeDone = {
|
||||||
onToggleDone = { checked ->
|
viewModel.updateTaskDone(task.id!!, true)
|
||||||
viewModel.updateTaskDone(task.id!!, checked)
|
},
|
||||||
|
onSwipeDelete = {
|
||||||
|
viewModel.deleteTask(task.id!!)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Divider between active and done (optional)
|
// Divider between active and done (optional)
|
||||||
if (done.isNotEmpty() && active.isNotEmpty()) {
|
if (done.isNotEmpty() && active.isNotEmpty()) {
|
||||||
@@ -71,16 +84,26 @@ fun TaskListScreen(
|
|||||||
items = done,
|
items = done,
|
||||||
key = { it.id!! }
|
key = { it.id!! }
|
||||||
) { task ->
|
) { task ->
|
||||||
|
Card(
|
||||||
|
onClick = { onTaskClick(task) },
|
||||||
|
//elevation = CardDefaults.elevatedCardElevation(defaultElevation = 2.dp),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
||||||
|
),
|
||||||
|
) {
|
||||||
TaskItemScreen(
|
TaskItemScreen(
|
||||||
modifier = Modifier.animateItem(),
|
modifier = Modifier.animateItem(),
|
||||||
viewModel = TaskItemViewModel(task),
|
viewModel = TaskItemViewModel(task),
|
||||||
onClick = { onTaskClick(task) },
|
onSwipeDone = {
|
||||||
onToggleDone = { checked ->
|
viewModel.updateTaskDone(task.id!!, false)
|
||||||
viewModel.updateTaskDone(task.id!!, checked)
|
},
|
||||||
}
|
onSwipeDelete = {
|
||||||
|
viewModel.deleteTask(task.id!!)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@@ -7,8 +7,9 @@ import androidx.lifecycle.SavedStateHandle
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
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.ToggleTaskDoneUseCase
|
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.ToggleTaskDoneUseCase
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
@@ -18,7 +19,8 @@ import javax.inject.Inject
|
|||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class TaskListViewModel @Inject constructor(
|
class TaskListViewModel @Inject constructor(
|
||||||
getTasks: GetTasksForListUseCase,
|
getTasks: GetTasksForListUseCase,
|
||||||
private val toggleTaskDone: ToggleTaskDoneUseCase,
|
private val toggleTaskDoneUseCase: ToggleTaskDoneUseCase,
|
||||||
|
private val deleteTaskListUseCase: DeleteTaskListUseCase,
|
||||||
savedStateHandle: SavedStateHandle
|
savedStateHandle: SavedStateHandle
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
@@ -40,7 +42,12 @@ class TaskListViewModel @Inject constructor(
|
|||||||
|
|
||||||
fun updateTaskDone(taskId: Long, isDone: Boolean) {
|
fun updateTaskDone(taskId: Long, isDone: Boolean) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
toggleTaskDone(taskId, isDone)
|
toggleTaskDoneUseCase(taskId, isDone)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun deleteTask(taskId: Long) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
deleteTaskListUseCase(taskId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user