Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
braiso-22 committed Apr 30, 2024
2 parents 2387776 + 125cd8b commit 9ca4f25
Show file tree
Hide file tree
Showing 17 changed files with 281 additions and 203 deletions.
9 changes: 9 additions & 0 deletions app/src/main/java/com/braiso_22/cozycave/di/AppModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.braiso_22.cozycave.feature_execution.data.local.ExecutionRepositoryIm
import com.braiso_22.cozycave.feature_execution.data.local.dao.ExecutionDao
import com.braiso_22.cozycave.feature_execution.domain.ExecutionRepository
import com.braiso_22.cozycave.feature_execution.domain.use_case.AddExecutionUseCase
import com.braiso_22.cozycave.feature_execution.domain.use_case.DeleteExecutionUseCase
import com.braiso_22.cozycave.feature_execution.domain.use_case.GetExecutionByIdUseCase
import com.braiso_22.cozycave.feature_execution.domain.use_case.GetExecutionsByRelatedIdUseCase
import com.braiso_22.cozycave.feature_task.data.TaskRepositoryImpl
Expand Down Expand Up @@ -112,4 +113,12 @@ object AppModule {
getTaskByIdUseCase,
getExecutionsByRelatedIdUseCase
)

@Provides
@Singleton
fun provideDeleteExecutionUseCase(
executionRepository: ExecutionRepository,
): DeleteExecutionUseCase = DeleteExecutionUseCase(
executionRepository
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@ class ExecutionRepositoryFake : ExecutionRepository {
override suspend fun getExecutionById(id: Int): Execution {
TODO("Not yet implemented")
}

override suspend fun deleteExecution(execution: Execution) {
TODO("Not yet implemented")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ class ExecutionRepositoryImpl(private val dao: ExecutionDao) : ExecutionReposito
relatedId = 0
)
}

override suspend fun deleteExecution(execution: Execution) {
dao.deleteExecutionById(execution.toLocal())
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.braiso_22.cozycave.feature_execution.data.local.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.*
import com.braiso_22.cozycave.feature_execution.data.local.entities.LocalExecution
import com.braiso_22.cozycave.feature_execution.domain.Execution
import kotlinx.coroutines.flow.Flow

/**
Expand All @@ -20,4 +18,7 @@ interface ExecutionDao {

@Query("SELECT * FROM LocalExecution WHERE id = :id LIMIT 1")
suspend fun getExecutionById(id: Int): LocalExecution?

@Delete
suspend fun deleteExecutionById(execution: LocalExecution)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,11 @@ import kotlinx.coroutines.flow.Flow
* It is used to abstract the data source from the domain layer.
*/
interface ExecutionRepository {
/**
* Adds an [Execution] to the data source.
*/
suspend fun addExecution(execution: Execution)

/**
* Returns a [Flow] of all the [Execution]s related to a specific id.
*/
fun getExecutionsByRelatedId(id: Int): Flow<List<Execution>>

/**
* Returns an [Execution] by its id.
*/
suspend fun getExecutionById(id: Int): Execution

suspend fun deleteExecution(execution: Execution)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.braiso_22.cozycave.feature_execution.domain.use_case

import com.braiso_22.cozycave.feature_execution.domain.Execution
import com.braiso_22.cozycave.feature_execution.domain.ExecutionRepository

class DeleteExecutionUseCase(private val repository: ExecutionRepository) {
suspend operator fun invoke(execution: Execution) = repository.deleteExecution(execution)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class TaskRepositoryImpl(private val taskDao: TaskDao) : TaskRepository {
taskDao.insertTask(task.toLocal())
}

override suspend fun deleteTask(task: Task) {
TODO("Not yet implemented")
override suspend fun deleteTaskById(task: Task) {
taskDao.deleteTask(task.toLocal())
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,14 @@
package com.braiso_22.cozycave.feature_task.domain

import com.braiso_22.cozycave.feature_task.domain.Task
import kotlinx.coroutines.flow.Flow

/**
* Repository interface to be implemented in the data layer for accessing the [Task]s
*/
interface TaskRepository {
/**
* Returns a [Flow] of all the [Task]s.
*/

fun getTasks(): Flow<List<Task>>
/**
* Returns a [Task] by its id.
*/

suspend fun getTaskById(id: Int): Task
/**
* Inserts a [Task] into the database.
*/

suspend fun insertTask(task: Task)
/**
* Deletes a [Task] from the database.
*/
suspend fun deleteTask(task: Task)

suspend fun deleteTaskById(task: Task)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ package com.braiso_22.cozycave.feature_task.domain.use_case
import com.braiso_22.cozycave.feature_task.domain.Task
import com.braiso_22.cozycave.feature_task.domain.TaskRepository

/**
* Use case for deleting a [Task].
*/
class DeleteTaskUseCase(
private val taskRepository: TaskRepository
private val taskRepository: TaskRepository,
) {
suspend operator fun invoke(task: Task) = taskRepository.deleteTask(task)
suspend operator fun invoke(task: Task) = taskRepository.deleteTaskById(task)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,21 @@ import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.braiso_22.cozycave.R
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.components.CompletedExecutionComponent
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.components.UnCompletedExecutionComponent
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.components.ExecutionComponent
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.state.TaskDetailUiState

@Composable
Expand All @@ -32,12 +32,36 @@ fun TaskDetailScreen(
modifier: Modifier = Modifier,
viewModel: TaskDetailViewModel = hiltViewModel(),
) {
val context = LocalContext.current
val state = viewModel.state.value
val snackbarHostState = remember {
SnackbarHostState()
}

LaunchedEffect(key1 = true) {
viewModel.eventFlow.collect { event ->
when (event) {
TaskDetailViewModel.ExecutionUiEvent.ShowUiMessage -> {
val result = snackbarHostState.showSnackbar(
message = context.getString(R.string.execution_deleted),
actionLabel = context.getString(R.string.undo)
)
if (result == SnackbarResult.ActionPerformed) {
viewModel.onCancelDeletion()
}
}
}
}
}

TaskDetailScreenContent(
state = state,
windowSizeClass = windowSizeClass,
snackbarHostState = snackbarHostState,
onBack = onBack,
onClickTaskExecution = onClickTaskExecution,
onDeleteExecution = {
viewModel.onDeleteExecution(it)
},
onEditExecution = onClickTaskExecution,
modifier = modifier,
)
}
Expand All @@ -46,8 +70,9 @@ fun TaskDetailScreen(
@Composable
fun TaskDetailScreenContent(
state: TaskDetailUiState,
windowSizeClass: WindowSizeClass,
onClickTaskExecution: (Int, Int) -> Unit,
snackbarHostState: SnackbarHostState,
onEditExecution: (Int, Int) -> Unit,
onDeleteExecution: (Int) -> Unit,
onBack: () -> Unit,
modifier: Modifier = Modifier,
) {
Expand All @@ -74,6 +99,9 @@ fun TaskDetailScreenContent(
},
)
},
snackbarHost = {
SnackbarHost(hostState = snackbarHostState)
}
) { padding ->
LazyColumn(
modifier = Modifier
Expand Down Expand Up @@ -112,13 +140,15 @@ fun TaskDetailScreenContent(
}
}
itemsIndexed(state.unFinishedExecutions) { index, execution ->
UnCompletedExecutionComponent(
ExecutionComponent(
state = execution,
onDelete = onDeleteExecution,
onEdit = { onEditExecution(state.taskId, execution.id) },
canModify = true,
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
.clickable {
onClickTaskExecution(state.taskId, execution.id)

}
)
if (index != state.unFinishedExecutions.lastIndex)
Expand All @@ -141,13 +171,15 @@ fun TaskDetailScreenContent(
}

itemsIndexed(state.completedExecutions) { index, execution ->
CompletedExecutionComponent(
ExecutionComponent(
state = execution,
onDelete = onDeleteExecution,
onEdit = { onEditExecution(state.taskId, execution.id) },
canModify = true,
modifier = Modifier
.fillMaxSize()
.padding(8.dp)
.clickable {
onClickTaskExecution(state.taskId, execution.id)

}
)
if (index != state.completedExecutions.lastIndex)
Expand All @@ -161,7 +193,6 @@ fun TaskDetailScreenContent(
}
}

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@Composable
private fun TaskDetailScreenContentPreview(dpSize: DpSize) {
val state = remember {
Expand All @@ -171,9 +202,10 @@ private fun TaskDetailScreenContentPreview(dpSize: DpSize) {
}
TaskDetailScreenContent(
state = state.value,
windowSizeClass = WindowSizeClass.calculateFromSize(dpSize),
snackbarHostState = SnackbarHostState(),
onBack = {},
onClickTaskExecution = { taskId, executionId ->
onDeleteExecution = {},
onEditExecution = { taskId, executionId ->

},
modifier = Modifier.fillMaxSize()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@ import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.braiso_22.cozycave.feature_execution.domain.Execution
import com.braiso_22.cozycave.feature_execution.domain.use_case.AddExecutionUseCase
import com.braiso_22.cozycave.feature_execution.domain.use_case.DeleteExecutionUseCase
import com.braiso_22.cozycave.feature_execution.domain.use_case.GetExecutionByIdUseCase
import com.braiso_22.cozycave.feature_task.domain.use_case.GetTaskWithExecutionsUseCase
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.state.TaskDetailUiState
import com.braiso_22.cozycave.feature_task.presentation.show_task_detail.state.toUiState
import com.braiso_22.cozycave.feature_task.presentation.tasks.TasksViewModel.TaskUiEvent
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject
Expand All @@ -20,12 +27,21 @@ const val TAG = "TaskDetailViewModel"
@HiltViewModel
class TaskDetailViewModel @Inject constructor(
private val getTaskWithExecutionsUseCase: GetTaskWithExecutionsUseCase,
private val deleteExecutionUseCase: DeleteExecutionUseCase,
private val addExecutionUseCase: AddExecutionUseCase,
private val getExecutionByIdUseCase: GetExecutionByIdUseCase,
private val savedStateHandle: SavedStateHandle,
) : ViewModel() {

private val _state = mutableStateOf(TaskDetailUiState(taskId = 0))
val state: State<TaskDetailUiState> = _state

private val _eventFlow = MutableSharedFlow<ExecutionUiEvent>()

val eventFlow = _eventFlow.asSharedFlow()

private var lastDeletedExecution: Execution? = null

private val _taskId = mutableIntStateOf(0)

init {
Expand All @@ -40,4 +56,24 @@ class TaskDetailViewModel @Inject constructor(
}
}
}

fun onDeleteExecution(id: Int) {
viewModelScope.launch {
val execution = getExecutionByIdUseCase(id)
lastDeletedExecution = execution
deleteExecutionUseCase(execution)
_eventFlow.emit(ExecutionUiEvent.ShowUiMessage)
}
}

fun onCancelDeletion() {
viewModelScope.launch {
addExecutionUseCase(lastDeletedExecution ?: return@launch)
lastDeletedExecution = null
}
}

sealed class ExecutionUiEvent {
data object ShowUiMessage : ExecutionUiEvent()
}
}
Loading

0 comments on commit 9ca4f25

Please sign in to comment.