Skip to content

Commit fe69d66

Browse files
authored
[feature/setup-navigation] Set up navigation between Home-Post screens (#17)
* Set up navigation between home and post * Add DeleteTaskDialog * Change method of deleteTask in repository * Add delete dialog show logic and delete logic * Change container color of dialog
1 parent 263d944 commit fe69d66

File tree

12 files changed

+237
-15
lines changed

12 files changed

+237
-15
lines changed

app/src/main/java/com/conf/mad/todo/TodoApp.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.conf.mad.todo.designsystem.TodoTheme
88
import com.conf.mad.todo.home.HOME_SCREEN_ROUTE
99
import com.conf.mad.todo.home.homeScreen
1010
import com.conf.mad.todo.post.POST_SCREEN_ROUTE
11+
import com.conf.mad.todo.post.POST_SCREEN_TASK_DEFAULT_ID
1112
import com.conf.mad.todo.post.postScreen
1213

1314
@Composable
@@ -19,8 +20,19 @@ fun TodoApp(
1920
navController = navController,
2021
startDestination = HOME_SCREEN_ROUTE
2122
) {
22-
homeScreen(onPost = { navController.navigate(POST_SCREEN_ROUTE) })
23-
postScreen()
23+
homeScreen(
24+
onPost = {
25+
navController.navigate("${POST_SCREEN_ROUTE}/${POST_SCREEN_TASK_DEFAULT_ID}")
26+
}
27+
)
28+
postScreen(
29+
onCancel = { navController.popBackStack() },
30+
onComplete = {
31+
navController.navigate(HOME_SCREEN_ROUTE) {
32+
launchSingleTop = true
33+
}
34+
}
35+
)
2436
}
2537
}
2638
}

core/ui/src/main/java/com/conf/mad/todo/ui/Clickable.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.conf.mad.todo.ui
22

3+
import androidx.compose.foundation.ExperimentalFoundationApi
34
import androidx.compose.foundation.clickable
5+
import androidx.compose.foundation.combinedClickable
46
import androidx.compose.foundation.interaction.MutableInteractionSource
57
import androidx.compose.runtime.Composable
68
import androidx.compose.runtime.remember
@@ -18,3 +20,17 @@ inline fun Modifier.noRippleClickable(
1820
onClick()
1921
}
2022
)
23+
24+
@OptIn(ExperimentalFoundationApi::class)
25+
@Composable
26+
inline fun Modifier.noRippleCombinedClickable(
27+
noinline onClick: () -> Unit,
28+
noinline onLongClick: () -> Unit
29+
): Modifier = composed {
30+
this.combinedClickable(
31+
onClick = onClick,
32+
onLongClick = onLongClick,
33+
indication = null,
34+
interactionSource = remember { MutableInteractionSource() }
35+
)
36+
}

data/task/src/main/java/com/conf/mad/todo/data/task/repository/DefaultTaskRepository.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class DefaultTaskRepository @Inject constructor(
2525
}
2626

2727
override suspend fun deleteTask(task: Task) {
28-
taskDao.insertTask(task.toEntity())
28+
taskDao.deleteTask(task.toEntity())
2929
}
3030

3131
override suspend fun updateFavorite(id: Long, isFavorite: Boolean) {

feature/home/src/main/java/com/conf/mad/todo/home/HomeScreen.kt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import androidx.compose.material3.Scaffold
1212
import androidx.compose.material3.Text
1313
import androidx.compose.runtime.Composable
1414
import androidx.compose.runtime.getValue
15+
import androidx.compose.runtime.remember
1516
import androidx.compose.ui.Modifier
1617
import androidx.compose.ui.unit.dp
1718
import androidx.hilt.navigation.compose.hiltViewModel
@@ -20,6 +21,7 @@ import androidx.navigation.NavGraphBuilder
2021
import androidx.navigation.compose.composable
2122
import com.conf.mad.todo.designsystem.TodoTheme
2223
import com.conf.mad.todo.designsystem.preview.DevicePreview
24+
import com.conf.mad.todo.home.component.DeleteTaskDialog
2325
import com.conf.mad.todo.home.component.HomeBottomAppBar
2426
import com.conf.mad.todo.home.component.HomeTopAppBar
2527
import com.conf.mad.todo.home.component.TaskItem
@@ -47,8 +49,12 @@ fun HomeScreen(
4749
viewModel: HomeViewModel = hiltViewModel()
4850
) {
4951
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
52+
val isDeleteDialogVisible = remember(uiState.taskToDelete) {
53+
uiState.taskToDelete != null
54+
}
5055
HomeScreen(
5156
isCompletedTaskVisible = uiState.isCompletedTaskVisible,
57+
isDeleteDialogVisible = isDeleteDialogVisible,
5258
currentDestination = uiState.currentDestination,
5359
todos = uiState.todoTasks,
5460
completedTasks = uiState.completedTasks,
@@ -57,12 +63,16 @@ fun HomeScreen(
5763
onPost = onPost,
5864
onFavoriteChanged = viewModel::onFavoriteChanged,
5965
onCompletedChanged = viewModel::onCompletedChanged,
66+
onSelectTaskToDelete = viewModel::onSelectTaskToDelete,
67+
onDeleteDialogDismiss = viewModel::onDismissDeleteDialog,
68+
onDeleteTask = viewModel::onDeleteTask
6069
)
6170
}
6271

6372
@Composable
6473
fun HomeScreen(
6574
isCompletedTaskVisible: Boolean,
75+
isDeleteDialogVisible: Boolean,
6676
currentDestination: HomeMenu,
6777
todos: ImmutableList<TaskUiModel>,
6878
completedTasks: ImmutableList<TaskUiModel>,
@@ -71,6 +81,9 @@ fun HomeScreen(
7181
onPost: () -> Unit,
7282
onFavoriteChanged: (Long, Boolean) -> Unit,
7383
onCompletedChanged: (Long, Boolean) -> Unit,
84+
onSelectTaskToDelete: (task: TaskUiModel) -> Unit,
85+
onDeleteDialogDismiss: () -> Unit,
86+
onDeleteTask: () -> Unit
7487
) {
7588
Scaffold(
7689
modifier = Modifier
@@ -129,6 +142,7 @@ fun HomeScreen(
129142
!todo.isFavorite
130143
)
131144
},
145+
onDeleteDialogShow = { onSelectTaskToDelete(todo) }
132146
)
133147
}
134148
if (isCompletedTaskVisible) {
@@ -159,10 +173,17 @@ fun HomeScreen(
159173
!task.isFavorite
160174
)
161175
},
176+
onDeleteDialogShow = { onSelectTaskToDelete(task) }
162177
)
163178
}
164179
}
165180
}
181+
if (isDeleteDialogVisible) {
182+
DeleteTaskDialog(
183+
onDismissRequest = onDeleteDialogDismiss,
184+
onConfirm = onDeleteTask
185+
)
186+
}
166187
}
167188
}
168189

@@ -204,6 +225,7 @@ private fun HomeScreenPreview() {
204225
TodoTheme {
205226
HomeScreen(
206227
isCompletedTaskVisible = true,
228+
isDeleteDialogVisible = false,
207229
currentDestination = HomeMenu.POST,
208230
todos = todos,
209231
completedTasks = completedTasks,
@@ -212,6 +234,9 @@ private fun HomeScreenPreview() {
212234
onPost = {},
213235
onFavoriteChanged = { _, _ -> },
214236
onCompletedChanged = { _, _ -> },
237+
onSelectTaskToDelete = {},
238+
onDeleteDialogDismiss = {},
239+
onDeleteTask = {}
215240
)
216241
}
217242
}

feature/home/src/main/java/com/conf/mad/todo/home/HomeViewModel.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,26 @@ class HomeViewModel @Inject constructor(
7474
repository.updateCompleted(id, isCompleted)
7575
}
7676
}
77+
78+
fun onSelectTaskToDelete(task: TaskUiModel) {
79+
_uiState.update {
80+
it.copy(taskToDelete = task)
81+
}
82+
}
83+
84+
fun onDeleteTask() {
85+
viewModelScope.launch {
86+
val task = uiState.value.taskToDelete ?: return@launch
87+
repository.deleteTask(task.asDomain())
88+
_uiState.update {
89+
it.copy(taskToDelete = null)
90+
}
91+
}
92+
}
93+
94+
fun onDismissDeleteDialog() {
95+
_uiState.update {
96+
it.copy(taskToDelete = null)
97+
}
98+
}
7799
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package com.conf.mad.todo.home.component
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.Row
6+
import androidx.compose.foundation.layout.Spacer
7+
import androidx.compose.foundation.layout.fillMaxSize
8+
import androidx.compose.foundation.layout.fillMaxWidth
9+
import androidx.compose.foundation.layout.height
10+
import androidx.compose.foundation.layout.padding
11+
import androidx.compose.foundation.layout.width
12+
import androidx.compose.foundation.shape.RoundedCornerShape
13+
import androidx.compose.material3.Card
14+
import androidx.compose.material3.CardDefaults
15+
import androidx.compose.material3.Text
16+
import androidx.compose.material3.TextButton
17+
import androidx.compose.runtime.Composable
18+
import androidx.compose.ui.Alignment
19+
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.unit.dp
21+
import androidx.compose.ui.unit.sp
22+
import androidx.compose.ui.window.Dialog
23+
import com.conf.mad.todo.designsystem.TodoTheme
24+
import com.conf.mad.todo.designsystem.preview.DevicePreview
25+
26+
@Composable
27+
fun DeleteTaskDialog(
28+
onDismissRequest: () -> Unit,
29+
onConfirm: () -> Unit
30+
) {
31+
Dialog(onDismissRequest = onDismissRequest) {
32+
Card(
33+
modifier = Modifier
34+
.padding(16.dp)
35+
.height(240.dp)
36+
.fillMaxWidth(),
37+
shape = RoundedCornerShape(4.dp),
38+
colors = CardDefaults.cardColors(containerColor = TodoTheme.colors.surface)
39+
) {
40+
Column(
41+
modifier = Modifier
42+
.fillMaxSize()
43+
.padding(24.dp),
44+
verticalArrangement = Arrangement.SpaceBetween
45+
) {
46+
Column(modifier = Modifier.fillMaxWidth()) {
47+
Text(
48+
text = "투두를 삭제할까요?",
49+
style = TodoTheme.typography.medium1.copy(fontSize = 20.sp),
50+
color = TodoTheme.colors.onSurface60
51+
)
52+
Spacer(modifier = Modifier.height(16.dp))
53+
Text(
54+
text = "삭제하면 되돌릴 수 없어요.",
55+
style = TodoTheme.typography.regular1,
56+
color = TodoTheme.colors.onSurface50
57+
)
58+
}
59+
Row(
60+
modifier = Modifier.fillMaxWidth(),
61+
horizontalArrangement = Arrangement.End,
62+
verticalAlignment = Alignment.Bottom
63+
) {
64+
TextButton(
65+
onClick = onDismissRequest,
66+
) {
67+
Text(
68+
text = "취소",
69+
style = TodoTheme.typography.medium1,
70+
color = TodoTheme.colors.onSurface60
71+
)
72+
}
73+
Spacer(modifier = Modifier.width(8.dp))
74+
TextButton(
75+
onClick = onConfirm,
76+
) {
77+
Text(
78+
text = "삭제하기",
79+
style = TodoTheme.typography.medium1,
80+
color = TodoTheme.colors.primary
81+
)
82+
}
83+
}
84+
}
85+
}
86+
}
87+
}
88+
89+
@DevicePreview
90+
@Composable
91+
private fun DeleteTaskDialogPreview() {
92+
TodoTheme {
93+
DeleteTaskDialog(
94+
onDismissRequest = {},
95+
onConfirm = {}
96+
)
97+
}
98+
}

feature/home/src/main/java/com/conf/mad/todo/home/component/TaskItem.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.conf.mad.todo.home.component
22

3+
import androidx.compose.foundation.ExperimentalFoundationApi
34
import androidx.compose.foundation.Image
45
import androidx.compose.foundation.background
6+
import androidx.compose.foundation.combinedClickable
57
import androidx.compose.foundation.layout.Arrangement
68
import androidx.compose.foundation.layout.Row
79
import androidx.compose.foundation.layout.Spacer
@@ -20,6 +22,7 @@ import com.conf.mad.todo.home.R
2022
import com.conf.mad.todo.home.model.TaskStatus
2123
import com.conf.mad.todo.ui.noRippleClickable
2224

25+
@OptIn(ExperimentalFoundationApi::class)
2326
@Composable
2427
internal fun TaskItem(
2528
modifier: Modifier = Modifier,
@@ -28,6 +31,7 @@ internal fun TaskItem(
2831
isFavorite: Boolean,
2932
onCompletedValueChange: () -> Unit,
3033
onFavoriteValueChange: () -> Unit,
34+
onDeleteDialogShow: () -> Unit
3135
) {
3236
Row(
3337
modifier = modifier
@@ -37,7 +41,10 @@ internal fun TaskItem(
3741
) {
3842
Row(
3943
modifier = Modifier
40-
.noRippleClickable(onClick = onCompletedValueChange),
44+
.combinedClickable(
45+
onClick = onCompletedValueChange,
46+
onLongClick = onDeleteDialogShow
47+
).weight(1f),
4148
verticalAlignment = Alignment.CenterVertically
4249
) {
4350
Image(
@@ -93,7 +100,8 @@ private fun TaskItemPreview() {
93100
status = TaskStatus.DONE,
94101
isFavorite = false,
95102
onCompletedValueChange = {},
96-
onFavoriteValueChange = {}
103+
onFavoriteValueChange = {},
104+
onDeleteDialogShow = {}
97105
)
98106
}
99107
}

feature/home/src/main/java/com/conf/mad/todo/home/model/HomeUiState.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import kotlinx.collections.immutable.persistentListOf
66
data class HomeUiState(
77
val isCompletedTaskVisible: Boolean = true,
88
val currentDestination: HomeMenu = HomeMenu.TASK,
9+
val taskToDelete: TaskUiModel? = null,
910
val todoTasks: ImmutableList<TaskUiModel> = persistentListOf(),
1011
val completedTasks: ImmutableList<TaskUiModel> = persistentListOf()
1112
) {

feature/home/src/main/java/com/conf/mad/todo/home/model/TaskUiModel.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ data class TaskUiModel(
2020
isFavorite = task.isFavorite
2121
)
2222

23+
fun asDomain() = Task(
24+
id = id,
25+
title = title,
26+
description = description,
27+
isFavorite = isFavorite,
28+
isCompleted = isCompleted
29+
)
30+
2331
companion object {
2432
fun of(task: Task) = TaskUiModel(task)
2533
}

0 commit comments

Comments
 (0)