Skip to content

Commit 5a07cf1

Browse files
authored
Merge pull request #185 from YAPP-Github/qa/#184-sprint-qa-dh
[QA/#184] 스프린트 QA를 반영합니다.
2 parents 297d837 + 107f244 commit 5a07cf1

6 files changed

Lines changed: 117 additions & 28 deletions

File tree

core/designsystem/src/main/java/com/threegap/bitnagil/designsystem/component/block/BitnagilTopBar.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import com.threegap.bitnagil.designsystem.BitnagilTheme
1818
import com.threegap.bitnagil.designsystem.R
1919
import com.threegap.bitnagil.designsystem.component.atom.BitnagilIcon
2020
import com.threegap.bitnagil.designsystem.component.atom.BitnagilIconButton
21+
import com.threegap.bitnagil.designsystem.modifier.throttled
2122

2223
@Composable
2324
fun BitnagilTopBar(
@@ -35,7 +36,7 @@ fun BitnagilTopBar(
3536
if (showBackButton) {
3637
BitnagilIconButton(
3738
id = R.drawable.ic_chevron_left_lg,
38-
onClick = onBackClick,
39+
onClick = throttled { onBackClick() },
3940
tint = BitnagilTheme.colors.coolGray10,
4041
modifier = Modifier
4142
.align(Alignment.CenterStart),
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.threegap.bitnagil.designsystem.modifier
2+
3+
import android.os.SystemClock
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.getValue
6+
import androidx.compose.runtime.remember
7+
import androidx.compose.runtime.rememberUpdatedState
8+
9+
class ClickThrottler(private val throttleTimeMs: Long = 500L) {
10+
private var lastClickTime: Long = 0L
11+
12+
fun processEvent(event: () -> Unit) {
13+
val now = SystemClock.elapsedRealtime()
14+
if (now - lastClickTime >= throttleTimeMs) {
15+
lastClickTime = now
16+
event()
17+
}
18+
}
19+
}
20+
21+
@Composable
22+
fun throttled(
23+
throttleTimeMs: Long = 500L,
24+
onClick: () -> Unit,
25+
): () -> Unit {
26+
val currentOnClick by rememberUpdatedState(onClick)
27+
val throttler = remember(throttleTimeMs) { ClickThrottler(throttleTimeMs) }
28+
29+
return remember(throttler) {
30+
{ throttler.processEvent { currentOnClick() } }
31+
}
32+
}
Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,19 @@
11
package com.threegap.bitnagil.designsystem.modifier
22

33
import androidx.compose.foundation.clickable
4-
import androidx.compose.foundation.interaction.MutableInteractionSource
5-
import androidx.compose.runtime.remember
64
import androidx.compose.ui.Modifier
7-
import androidx.compose.ui.composed
85
import androidx.compose.ui.semantics.Role
96

107
fun Modifier.clickableWithoutRipple(
118
enabled: Boolean = true,
129
onClickLabel: String? = null,
1310
role: Role? = null,
1411
onClick: () -> Unit,
15-
) = composed {
16-
clickable(
17-
indication = null,
18-
interactionSource = remember { MutableInteractionSource() },
19-
enabled = enabled,
20-
onClickLabel = onClickLabel,
21-
role = role,
22-
onClick = onClick,
23-
)
24-
}
12+
) = this.clickable(
13+
interactionSource = null,
14+
indication = null,
15+
enabled = enabled,
16+
onClickLabel = onClickLabel,
17+
role = role,
18+
onClick = onClick,
19+
)

presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/RoutineListScreen.kt

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import androidx.compose.runtime.getValue
1616
import androidx.compose.ui.Alignment
1717
import androidx.compose.ui.Modifier
1818
import androidx.compose.ui.tooling.preview.Preview
19+
import androidx.compose.ui.tooling.preview.PreviewParameter
1920
import androidx.compose.ui.unit.dp
2021
import androidx.hilt.navigation.compose.hiltViewModel
2122
import com.threegap.bitnagil.designsystem.BitnagilTheme
@@ -28,6 +29,7 @@ import com.threegap.bitnagil.presentation.routinelist.component.template.Routine
2829
import com.threegap.bitnagil.presentation.routinelist.component.template.WeeklyDatePicker
2930
import com.threegap.bitnagil.presentation.routinelist.contract.RoutineListSideEffect
3031
import com.threegap.bitnagil.presentation.routinelist.contract.RoutineListState
32+
import com.threegap.bitnagil.presentation.routinelist.model.RoutineListStatePreviewProvider
3133
import com.threegap.bitnagil.presentation.routinelist.model.RoutineUiModel
3234
import org.orbitmvi.orbit.compose.collectAsState
3335
import org.orbitmvi.orbit.compose.collectSideEffect
@@ -133,7 +135,6 @@ private fun RoutineListScreen(
133135
items(
134136
items = uiState.selectedDateRoutines,
135137
key = { routine -> routine.routineId },
136-
contentType = { "routine_item" },
137138
) { routine ->
138139
RoutineDetailsCard(
139140
routine = routine,
@@ -148,13 +149,17 @@ private fun RoutineListScreen(
148149

149150
@Preview
150151
@Composable
151-
private fun RoutineListScreenPreview() {
152-
RoutineListScreen(
153-
uiState = RoutineListState.INIT,
154-
onDateSelect = {},
155-
onShowDeleteConfirmBottomSheet = {},
156-
onShowEditConfirmBottomSheet = {},
157-
onRegisterRoutineClick = {},
158-
onBackClick = {},
159-
)
152+
private fun RoutineListScreenPreview(
153+
@PreviewParameter(RoutineListStatePreviewProvider::class) uiState: RoutineListState,
154+
) {
155+
BitnagilTheme {
156+
RoutineListScreen(
157+
uiState = uiState,
158+
onDateSelect = {},
159+
onShowDeleteConfirmBottomSheet = {},
160+
onShowEditConfirmBottomSheet = {},
161+
onRegisterRoutineClick = {},
162+
onBackClick = {},
163+
)
164+
}
160165
}

presentation/src/main/java/com/threegap/bitnagil/presentation/routinelist/component/template/RoutineDetailsCard.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Arrangement
55
import androidx.compose.foundation.layout.Column
66
import androidx.compose.foundation.layout.PaddingValues
77
import androidx.compose.foundation.layout.Row
8-
import androidx.compose.foundation.layout.Spacer
98
import androidx.compose.foundation.layout.fillMaxWidth
109
import androidx.compose.foundation.layout.padding
1110
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -70,11 +69,11 @@ fun RoutineDetailsCard(
7069
text = routine.routineName,
7170
color = BitnagilTheme.colors.coolGray10,
7271
style = BitnagilTheme.typography.body1SemiBold,
73-
modifier = Modifier.padding(start = 10.dp),
72+
modifier = Modifier
73+
.padding(start = 10.dp)
74+
.weight(1f),
7475
)
7576

76-
Spacer(modifier = Modifier.weight(1f))
77-
7877
if (!routine.routineDeletedYn) {
7978
BitnagilIconButton(
8079
id = R.drawable.ic_edit,
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.threegap.bitnagil.presentation.routinelist.model
2+
3+
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
4+
import com.threegap.bitnagil.domain.routine.model.DayOfWeek
5+
import com.threegap.bitnagil.presentation.routinelist.contract.RoutineListState
6+
import java.time.LocalDate
7+
8+
internal class RoutineListStatePreviewProvider : PreviewParameterProvider<RoutineListState> {
9+
override val values = sequenceOf(
10+
emptyRoutineState,
11+
withRoutinesState,
12+
)
13+
}
14+
15+
private val today = LocalDate.now()
16+
17+
private val sampleRoutines = listOf(
18+
RoutineUiModel(
19+
routineId = "1",
20+
routineName = "아침 스트레칭",
21+
repeatDay = listOf(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY),
22+
executionTime = "07:00:00",
23+
routineDate = today.toString(),
24+
startDate = "2025-01-01",
25+
endDate = "2025-12-31",
26+
routineDeletedYn = false,
27+
subRoutineNames = listOf("목 스트레칭", "어깨 스트레칭"),
28+
recommendedRoutineType = null,
29+
),
30+
RoutineUiModel(
31+
routineId = "2",
32+
routineName = "독서",
33+
repeatDay = emptyList(),
34+
executionTime = "09:00:00",
35+
routineDate = today.toString(),
36+
startDate = "2025-01-01",
37+
endDate = "2025-03-31",
38+
routineDeletedYn = false,
39+
subRoutineNames = emptyList(),
40+
recommendedRoutineType = null,
41+
),
42+
)
43+
44+
private val emptyRoutineState = RoutineListState.INIT
45+
46+
private val withRoutinesState = RoutineListState(
47+
isLoading = false,
48+
selectedDate = today,
49+
routines = RoutineScheduleUiModel(
50+
routines = mapOf(
51+
today.toString() to DailyRoutinesUiModel(routines = sampleRoutines),
52+
),
53+
),
54+
selectedRoutine = null,
55+
deleteConfirmBottomSheetVisible = false,
56+
editConfirmBottomSheetVisible = false,
57+
)

0 commit comments

Comments
 (0)