mirror of
https://github.com/wismna/DoNext.git
synced 2025-12-06 00:02:40 -05:00
Use events for task clicks
This commit is contained in:
@@ -13,14 +13,12 @@ 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.domain.model.Task
|
||||
import com.wismna.geoffroy.donext.presentation.viewmodel.DueTodayViewModel
|
||||
|
||||
@Composable
|
||||
fun DueTodayTasksScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: DueTodayViewModel = hiltViewModel(),
|
||||
onTaskClick: (task: Task) -> Unit
|
||||
) {
|
||||
val tasks = viewModel.dueTodayTasks
|
||||
|
||||
@@ -41,7 +39,6 @@ fun DueTodayTasksScreen(
|
||||
TaskItemScreen(
|
||||
modifier = Modifier.animateItem(),
|
||||
task = task,
|
||||
onTaskClick = { onTaskClick(task) },
|
||||
onSwipeLeft = {
|
||||
viewModel.updateTaskDone(task.id!!)
|
||||
Toast.makeText(context, "Task done", Toast.LENGTH_SHORT).show()
|
||||
|
||||
@@ -108,6 +108,7 @@ fun AppContent(
|
||||
navController.navigate(event.route)
|
||||
}
|
||||
is UiEvent.NavigateBack -> navController.popBackStack()
|
||||
is UiEvent.EditTask -> { viewModel.showTaskSheet = true }
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -207,10 +208,7 @@ fun AppContent(
|
||||
}
|
||||
|
||||
val taskListViewModel: TaskListViewModel = hiltViewModel(navBackStackEntry)
|
||||
TaskListScreen(
|
||||
viewModel = taskListViewModel,
|
||||
onTaskClick = { task -> viewModel.onTaskClicked(task) }
|
||||
)
|
||||
TaskListScreen(viewModel = taskListViewModel)
|
||||
}
|
||||
|
||||
composable(AppDestination.ManageLists.route) {
|
||||
@@ -220,16 +218,10 @@ fun AppContent(
|
||||
)
|
||||
}
|
||||
composable(AppDestination.DueTodayList.route) {
|
||||
DueTodayTasksScreen (
|
||||
modifier = Modifier,
|
||||
onTaskClick = { task -> viewModel.onTaskClicked(task) }
|
||||
)
|
||||
DueTodayTasksScreen (modifier = Modifier)
|
||||
}
|
||||
composable(AppDestination.RecycleBin.route) {
|
||||
RecycleBinScreen(
|
||||
modifier = Modifier,
|
||||
onTaskClick = { task -> viewModel.onTaskClicked(task) }
|
||||
)
|
||||
RecycleBinScreen(modifier = Modifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,14 +29,12 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import com.wismna.geoffroy.donext.domain.model.Task
|
||||
import com.wismna.geoffroy.donext.presentation.viewmodel.RecycleBinViewModel
|
||||
|
||||
@Composable
|
||||
fun RecycleBinScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
viewModel: RecycleBinViewModel = hiltViewModel(),
|
||||
onTaskClick: (task: Task) -> Unit
|
||||
) {
|
||||
val tasks = viewModel.deletedTasks
|
||||
|
||||
@@ -77,7 +75,6 @@ fun RecycleBinScreen(
|
||||
TaskItemScreen(
|
||||
modifier = Modifier.animateItem(),
|
||||
task = item.task,
|
||||
onTaskClick = { onTaskClick(item.task) },
|
||||
onSwipeLeft = {
|
||||
viewModel.restore(item.task.id!!)
|
||||
Toast.makeText(context, "Task restored", Toast.LENGTH_SHORT).show()
|
||||
|
||||
@@ -37,6 +37,7 @@ import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import com.wismna.geoffroy.donext.domain.model.Priority
|
||||
import com.wismna.geoffroy.donext.domain.model.Task
|
||||
import com.wismna.geoffroy.donext.presentation.viewmodel.TaskItemViewModel
|
||||
@@ -45,11 +46,11 @@ import com.wismna.geoffroy.donext.presentation.viewmodel.TaskItemViewModel
|
||||
fun TaskItemScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
task: Task,
|
||||
onTaskClick: (taskId: Long) -> Unit,
|
||||
viewModel: TaskItemViewModel = hiltViewModel<TaskItemViewModel>(),
|
||||
onSwipeLeft: () -> Unit,
|
||||
onSwipeRight: () -> Unit
|
||||
) {
|
||||
val viewModel = TaskItemViewModel(task)
|
||||
viewModel.populateTask(task)
|
||||
// TODO: change this
|
||||
val dismissState = rememberSwipeToDismissBoxState(
|
||||
confirmValueChange = {
|
||||
@@ -78,7 +79,7 @@ fun TaskItemScreen(
|
||||
)
|
||||
Card(
|
||||
modifier = modifier,
|
||||
onClick = { onTaskClick(viewModel.id) },
|
||||
onClick = { viewModel.onTaskClicked(task) },
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
||||
),
|
||||
@@ -109,7 +110,7 @@ fun TaskItemScreen(
|
||||
) {
|
||||
// Title
|
||||
Text(
|
||||
text = viewModel.name,
|
||||
text = viewModel.name!!,
|
||||
fontSize = 18.sp,
|
||||
style = baseStyle,
|
||||
modifier = Modifier
|
||||
@@ -150,7 +151,7 @@ fun TaskItemScreen(
|
||||
) {
|
||||
if (!viewModel.description.isNullOrBlank()) {
|
||||
Text(
|
||||
text = viewModel.description,
|
||||
text = viewModel.description!!,
|
||||
color = MaterialTheme.colorScheme.tertiary,
|
||||
style = baseStyle.copy(
|
||||
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
|
||||
|
||||
@@ -15,13 +15,12 @@ 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.domain.model.Task
|
||||
import com.wismna.geoffroy.donext.presentation.viewmodel.TaskListViewModel
|
||||
|
||||
@Composable
|
||||
fun TaskListScreen(
|
||||
viewModel: TaskListViewModel = hiltViewModel<TaskListViewModel>(),
|
||||
onTaskClick: (Task) -> Unit) {
|
||||
) {
|
||||
val tasks = viewModel.tasks
|
||||
|
||||
// Split tasks into active and done
|
||||
@@ -43,7 +42,6 @@ fun TaskListScreen(
|
||||
TaskItemScreen(
|
||||
modifier = Modifier.animateItem(),
|
||||
task = task,
|
||||
onTaskClick = { onTaskClick(task) },
|
||||
onSwipeLeft = {
|
||||
viewModel.updateTaskDone(task.id!!, true)
|
||||
Toast.makeText(context, "Task done", Toast.LENGTH_SHORT).show()
|
||||
@@ -74,7 +72,6 @@ fun TaskListScreen(
|
||||
TaskItemScreen(
|
||||
modifier = Modifier.animateItem(),
|
||||
task = task,
|
||||
onTaskClick = { onTaskClick(task) },
|
||||
onSwipeLeft = {
|
||||
viewModel.updateTaskDone(task.id!!, false)
|
||||
Toast.makeText(context, "Task in progress", Toast.LENGTH_SHORT).show()
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.wismna.geoffroy.donext.presentation.ui.events
|
||||
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class UiEventBus @Inject constructor() {
|
||||
private val _events = MutableSharedFlow<UiEvent>(replay = 1)
|
||||
val events = _events.asSharedFlow()
|
||||
|
||||
suspend fun send(event: UiEvent) {
|
||||
_events.emit(event)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.NavBackStackEntry
|
||||
import com.wismna.geoffroy.donext.domain.model.AppDestination
|
||||
import com.wismna.geoffroy.donext.domain.model.Task
|
||||
import com.wismna.geoffroy.donext.domain.usecase.GetTaskListsUseCase
|
||||
import com.wismna.geoffroy.donext.presentation.ui.events.UiEvent
|
||||
import com.wismna.geoffroy.donext.presentation.ui.events.UiEventBus
|
||||
@@ -68,13 +67,6 @@ class MainViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun onTaskClicked(task: Task) {
|
||||
showTaskSheet = true
|
||||
viewModelScope.launch {
|
||||
uiEventBus.send(UiEvent.EditTask(task))
|
||||
}
|
||||
}
|
||||
|
||||
fun onDismissTaskSheet() {
|
||||
showTaskSheet = false
|
||||
viewModelScope.launch {
|
||||
|
||||
@@ -1,31 +1,42 @@
|
||||
package com.wismna.geoffroy.donext.presentation.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.wismna.geoffroy.donext.domain.extension.toLocalDate
|
||||
import com.wismna.geoffroy.donext.domain.model.Priority
|
||||
import com.wismna.geoffroy.donext.domain.model.Task
|
||||
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.launch
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import java.time.format.TextStyle
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
class TaskItemViewModel(task: Task) {
|
||||
val id: Long = task.id!!
|
||||
val name: String = task.name
|
||||
val description: String? = task.description
|
||||
val isDone: Boolean = task.isDone
|
||||
val isDeleted: Boolean = task.isDeleted
|
||||
val priority: Priority = task.priority
|
||||
@HiltViewModel
|
||||
class TaskItemViewModel @Inject constructor(
|
||||
private val uiEventBus: UiEventBus
|
||||
): ViewModel() {
|
||||
var id: Long? = null
|
||||
var name: String? = null
|
||||
var description: String? = null
|
||||
var dueDate: Long? = null
|
||||
var isDone: Boolean = false
|
||||
var isDeleted: Boolean = false
|
||||
var priority: Priority = Priority.NORMAL
|
||||
|
||||
val today: LocalDate = LocalDate.now(ZoneId.systemDefault())
|
||||
|
||||
val isOverdue: Boolean = task.dueDate?.let { millis ->
|
||||
val isOverdue: Boolean = dueDate?.let { millis ->
|
||||
val dueDate = millis.toLocalDate()
|
||||
dueDate.isBefore(today)
|
||||
} ?: false
|
||||
|
||||
val dueDateText: String? = task.dueDate?.let { formatDueDate(it) }
|
||||
val dueDateText: String? = dueDate?.let { formatDueDate(it) }
|
||||
|
||||
private fun formatDueDate(dueMillis: Long): String {
|
||||
val dueDate = dueMillis.toLocalDate()
|
||||
@@ -40,4 +51,19 @@ class TaskItemViewModel(task: Task) {
|
||||
dueDate.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.getDefault()))
|
||||
}
|
||||
}
|
||||
|
||||
fun populateTask(task: Task) {
|
||||
id = task.id!!
|
||||
name = task.name
|
||||
description = task.description
|
||||
isDone = task.isDone
|
||||
isDeleted = task.isDeleted
|
||||
priority = task.priority
|
||||
}
|
||||
|
||||
fun onTaskClicked(task: Task) {
|
||||
viewModelScope.launch {
|
||||
uiEventBus.send(UiEvent.EditTask(task))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,8 +45,8 @@ class TaskViewModel @Inject constructor(
|
||||
viewModelScope.launch {
|
||||
uiEventBus.events.collect { event ->
|
||||
when (event) {
|
||||
is UiEvent.EditTask -> startEditTask(event.task)
|
||||
is UiEvent.CreateNewTask -> startNewTask(event.taskListId)
|
||||
is UiEvent.EditTask -> startEditTask(event.task)
|
||||
is UiEvent.CloseTask -> reset()
|
||||
else -> {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user