Skip to content

Commit c5baa66

Browse files
authored
Merge pull request #109 from YAPP-Github/fix/TNT-251
[TNT-251][TNT-238] 중복 클릭 방지 및 로딩 출력 구현
2 parents 9dae4e7 + 3cfd980 commit c5baa66

File tree

27 files changed

+158
-20
lines changed

27 files changed

+158
-20
lines changed

core/designsystem/src/main/java/co/kr/tnt/designsystem/snackbar/Snackbar.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ fun TnTSnackbar(
7373

7474
@Preview(showBackground = true)
7575
@Composable
76-
private fun TnTToastPreview() {
76+
private fun TnTSnackbarPreview() {
7777
TnTTheme {
7878
TnTSnackbar(
7979
snackbarData = object : SnackbarData {

core/ui/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ dependencies {
1515
implementation(projects.domain)
1616

1717
implementation(libs.accompanist.permissions)
18+
implementation(libs.androidx.compose.navigation)
1819
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package co.kr.tnt.ui.component
2+
3+
import androidx.compose.foundation.layout.Box
4+
import androidx.compose.foundation.layout.fillMaxSize
5+
import androidx.compose.material3.CircularProgressIndicator
6+
import androidx.compose.material3.Surface
7+
import androidx.compose.runtime.Composable
8+
import androidx.compose.ui.Alignment
9+
import androidx.compose.ui.Modifier
10+
import androidx.compose.ui.graphics.Color
11+
import co.kr.tnt.designsystem.theme.TnTTheme
12+
13+
@Composable
14+
fun TnTLoadingScreen(modifier: Modifier = Modifier) {
15+
Surface(
16+
modifier = modifier.fillMaxSize(),
17+
color = Color.Black.copy(alpha = 0.4f),
18+
) {
19+
TnTLoading(modifier = Modifier.fillMaxSize())
20+
}
21+
}
22+
23+
@Composable
24+
fun TnTLoading(modifier: Modifier) {
25+
Box(
26+
modifier = modifier,
27+
contentAlignment = Alignment.Center,
28+
) {
29+
CircularProgressIndicator(
30+
color = TnTTheme.colors.redColors.Red500,
31+
)
32+
}
33+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package co.kr.tnt.ui.extensions
2+
3+
import androidx.navigation.NavController
4+
5+
/**
6+
* Back button 연속 클릭 시 빈 화면이 출력되는 현상 방지
7+
*/
8+
fun NavController.safePopBackStack() {
9+
if (currentBackStackEntry?.lifecycle?.currentState == androidx.lifecycle.Lifecycle.State.RESUMED) {
10+
popBackStack()
11+
}
12+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package co.kr.tnt.ui.utils
2+
3+
import android.os.SystemClock
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.getValue
6+
import androidx.compose.runtime.mutableLongStateOf
7+
import androidx.compose.runtime.remember
8+
import androidx.compose.runtime.setValue
9+
10+
@Composable
11+
inline fun throttled(
12+
throttleTime: Long = 1500L,
13+
crossinline onClick: () -> Unit,
14+
): () -> Unit {
15+
var lastTimeClicked by remember { mutableLongStateOf(0L) }
16+
return {
17+
val now = SystemClock.uptimeMillis()
18+
if (now - lastTimeClicked >= throttleTime) {
19+
lastTimeClicked = now
20+
onClick()
21+
}
22+
}
23+
}

feature/login/src/main/java/co/kr/tnt/login/LoginViewModel.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ internal class LoginViewModel @Inject constructor(
6161
}
6262

6363
this@LoginViewModel.loginResult = loginResult
64+
clearAllChecks()
6465
sendEffect(LoginSideEffect.ShowTermBottomSheet)
6566
}.onFailure {
6667
// TODO resource
@@ -89,6 +90,14 @@ internal class LoginViewModel @Inject constructor(
8990
}
9091
}
9192

93+
private fun clearAllChecks() {
94+
updateState {
95+
copy(
96+
terms = terms.keys.associateWith { false },
97+
)
98+
}
99+
}
100+
92101
private fun navigateToSignup() {
93102
loginResult?.let { loginResult ->
94103
sendEffect(LoginSideEffect.NavigateToSignup(loginResult))

feature/main/src/main/java/co/kr/tnt/main/ui/TnTNavHost.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import co.kr.tnt.trainer.main.navigation.navigateToTrainerMain
2727
import co.kr.tnt.trainer.main.navigation.trainerMainScreen
2828
import co.kr.tnt.trainer.signup.navigation.navigateToTrainerSignUp
2929
import co.kr.tnt.trainer.signup.navigation.trainerSignUpScreen
30+
import co.kr.tnt.ui.extensions.safePopBackStack
3031
import co.kr.tnt.webview.navigateToWebView
3132
import co.kr.tnt.webview.webViewScreen
3233

@@ -65,29 +66,29 @@ fun TnTNavHost(
6566
navigateToTrainerSignUp = navController::navigateToTrainerSignUp,
6667
)
6768
trainerSignUpScreen(
68-
navigateToPrevious = navController::popBackStack,
69+
navigateToPrevious = navController::safePopBackStack,
6970
navigateToInvite = navController::navigateToTrainerInvite,
7071
)
7172
traineeSignUpScreen(
72-
navigateToPrevious = navController::popBackStack,
73+
navigateToPrevious = navController::safePopBackStack,
7374
navigateToConnect = {
7475
navController.navigateToTraineeConnect(isSkippable = true)
7576
},
7677
)
7778
trainerInviteScreen(
78-
navigateToPrevious = navController::popBackStack,
79+
navigateToPrevious = navController::safePopBackStack,
7980
navigateToHome = { navController.navigateToTrainerMain(clearBackStack = true) },
8081
)
8182
trainerConnectScreen(
82-
navigateToPrevious = navController::popBackStack,
83+
navigateToPrevious = navController::safePopBackStack,
8384
navigateToHome = { navController.navigateToTrainerMain(clearBackStack = true) },
8485
)
8586
traineeConnectScreen(
86-
navigateToPrevious = navController::popBackStack,
87+
navigateToPrevious = navController::safePopBackStack,
8788
navigateToHome = { navController.navigateToTraineeMain(clearBackStack = true) },
8889
)
8990
traineeMealRecordScreen(
90-
navigateToPrevious = navController::popBackStack,
91+
navigateToPrevious = navController::safePopBackStack,
9192
)
9293
trainerMainScreen(
9394
navigateToConnect = navController::navigateToTrainerConnect,
@@ -103,7 +104,7 @@ fun TnTNavHost(
103104
navigateToMealDetail = navController::navigateToTraineeMealRecordDetail,
104105
)
105106
webViewScreen(
106-
navigateToPrevious = navController::popBackStack,
107+
navigateToPrevious = navController::safePopBackStack,
107108
)
108109
}
109110
}

feature/trainee/connect/src/main/java/co/kr/tnt/trainee/connect/PTSessionFormPage.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import co.kr.tnt.designsystem.component.TnTTopBarWithBackButton
3131
import co.kr.tnt.designsystem.component.button.TnTBottomButton
3232
import co.kr.tnt.designsystem.theme.TnTTheme
3333
import co.kr.tnt.feature.trainee.connect.R
34+
import co.kr.tnt.ui.component.TnTLoadingScreen
35+
import co.kr.tnt.ui.utils.throttled
3436
import java.time.LocalDate
3537
import java.time.ZoneId
3638
import java.time.format.DateTimeFormatter
@@ -44,6 +46,7 @@ internal fun PTSessionFormPage(
4446
sessionStartDate: LocalDate?,
4547
completedSessionCount: String,
4648
totalSessionCount: String,
49+
isLoading: Boolean,
4750
onChangeSessionStartDate: (date: LocalDate) -> Unit,
4851
onChangeCompletedSessionCount: (count: String) -> Unit,
4952
onChangeTotalSessionCount: (count: String) -> Unit,
@@ -192,10 +195,14 @@ internal fun PTSessionFormPage(
192195
text = stringResource(uiResource.string.next),
193196
modifier = Modifier.align(Alignment.BottomCenter),
194197
enabled = isFormValid,
195-
onClick = onNextClick,
198+
onClick = throttled { onNextClick() },
196199
)
197200
}
198201
}
202+
203+
if (isLoading) {
204+
TnTLoadingScreen()
205+
}
199206
}
200207

201208
@Composable
@@ -275,6 +282,7 @@ private fun PTSessionFormPagePreview() {
275282
sessionStartDate = LocalDate.now(),
276283
completedSessionCount = "15",
277284
totalSessionCount = "10",
285+
isLoading = false,
278286
onNextClick = { },
279287
onBackClick = { },
280288
onChangeSessionStartDate = { },

feature/trainee/connect/src/main/java/co/kr/tnt/trainee/connect/TraineeConnectContract.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ internal class TraineeConnectContract {
1919
val trainerImage: String = "",
2020
val traineeName: String = "",
2121
val traineeImage: String = "",
22+
val isLoading: Boolean = false,
2223
) : UiState
2324

2425
sealed interface TraineeConnectUiEvent : UiEvent {

feature/trainee/connect/src/main/java/co/kr/tnt/trainee/connect/TraineeConnectScreen.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ private fun TraineeConnectScreen(
9393
sessionStartDate = state.sessionStartDate,
9494
completedSessionCount = state.completedSessionCount,
9595
totalSessionCount = state.totalSessionCount,
96+
isLoading = state.isLoading,
9697
onChangeSessionStartDate = onChangeSessionStartDate,
9798
onChangeCompletedSessionCount = onChangeCompletedSessionCount,
9899
onChangeTotalSessionCount = onChangeTotalSessionCount,

0 commit comments

Comments
 (0)