Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ internal fun HttpClientConfig<*>.installTodakunDefaults(
json(json)
}
install(HttpTimeout) {
requestTimeoutMillis = 15_000
connectTimeoutMillis = 10_000
socketTimeoutMillis = 15_000
requestTimeoutMillis = 100_000
connectTimeoutMillis = 100_000
socketTimeoutMillis = 100_000
}
install(DefaultRequest) {
url(baseUrl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
Expand Down Expand Up @@ -43,15 +42,12 @@ fun OnboardingRoute(
viewModel: OnboardingViewModel = hiltViewModel(),
) {
val state by viewModel.collectAsState()
var permissionHandled by rememberSaveable {
mutableStateOf(Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
}
val permissionLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
) {
// 권한을 허락하지 않더라도 앱 진입
permissionHandled = true
// 권한을 허락하지 않더라도 회원가입 진행
viewModel.confirmComplete(onboardingToken)
}
val signupErrorMessage = stringResource(R.string.onboarding_signup_error)
val invalidInputErrorMessage = stringResource(R.string.onboarding_invalid_input_error)
Expand All @@ -70,7 +66,7 @@ fun OnboardingRoute(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
} else {
onFinish()
viewModel.confirmComplete(onboardingToken)
}
}

Expand Down Expand Up @@ -129,21 +125,18 @@ fun OnboardingRoute(
isSubmitting = state.submitState is OnboardingSubmitState.Loading,
onLifeStageSelect = viewModel::selectLifeStage,
onRelationshipStatusSelect = viewModel::selectRelationshipStatus,
onNextClick = {
viewModel.confirmComplete(onboardingToken)
},
onNextClick = viewModel::clickComplete,
onBackClick = viewModel::clickBack,
modifier = modifier,
)
}

OnboardingStep.COMPLETE -> {
if (permissionHandled) {
CompleteScreen(
onFinish = onFinish,
modifier = modifier,
)
}
CompleteScreen(
isLoading = state.submitState is OnboardingSubmitState.Loading,
onFinish = onFinish,
modifier = modifier,
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ class OnboardingViewModel
}
}

fun clickComplete() =
intent {
postSideEffect(OnboardingSideEffect.PermissionRequest)
}

fun confirmComplete(onboardingToken: OnboardingToken) =
intent {
if (state.submitState is OnboardingSubmitState.Loading) return@intent
Expand All @@ -55,15 +60,15 @@ class OnboardingViewModel
postSideEffect(OnboardingSideEffect.InvalidInput)
return@intent
}
reduce { state.copy(submitState = OnboardingSubmitState.Loading) }
reduce { state.copy(submitState = OnboardingSubmitState.Loading, step = OnboardingStep.COMPLETE) }
signUpUseCase(
signupSubmission = signupSubmission,
onboardingToken = onboardingToken,
).onSuccess {
reduce { state.copy(submitState = OnboardingSubmitState.Success, step = OnboardingStep.COMPLETE) }
reduce { state.copy(submitState = OnboardingSubmitState.Success) }
postSideEffect(OnboardingSideEffect.PermissionRequest)
}.onFailure { e ->
reduce { state.copy(submitState = OnboardingSubmitState.Failure) }
reduce { state.copy(submitState = OnboardingSubmitState.Failure, step = OnboardingStep.EXTRA_QUESTION) }
postSideEffect(OnboardingSideEffect.Failure(e))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@ import kotlinx.coroutines.delay

@Composable
internal fun CompleteScreen(
isLoading: Boolean,
onFinish: () -> Unit,
modifier: Modifier = Modifier,
) {
val currentOnFinish by rememberUpdatedState(onFinish)
LaunchedEffect(Unit) {
delay(3000)
currentOnFinish()
LaunchedEffect(isLoading) {
if (!isLoading) {
delay(3000L)
currentOnFinish()
}
}
Box(
modifier =
Expand Down Expand Up @@ -83,6 +86,7 @@ internal fun CompleteScreen(
private fun CompleteScreenPreview() {
TodakunTheme {
CompleteScreen(
isLoading = false,
onFinish = {},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import com.kikidan.onboarding.model.OnboardingSheet
import com.kikidan.onboarding.model.OnboardingSideEffect
import com.kikidan.onboarding.model.OnboardingState
import com.kikidan.onboarding.model.OnboardingStep
import com.kikidan.onboarding.model.OnboardingSubmitState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
Expand Down Expand Up @@ -135,7 +134,17 @@ class OnboardingViewModelTest {
}

@Test
fun `마지막 스텝에서 다음을 누르면 완료 화면으로 전환된다`() =
fun `완료 단계에서 다음을 누르면 권한 요청 사이드이펙트가 먼저 전달된다`() =
runTest {
val initial = OnboardingState(step = OnboardingStep.EXTRA_QUESTION)
viewModel().test(this, initialState = initial) {
containerHost.clickComplete()
expectSideEffect(OnboardingSideEffect.PermissionRequest)
}
}

@Test
fun `가입 요청을 시작하면 응답을 기다리는 동안 완료 화면으로 전환된다`() =
runTest {
val initial =
OnboardingState(
Expand All @@ -150,9 +159,8 @@ class OnboardingViewModelTest {
)
viewModel().test(this, initialState = initial) {
containerHost.confirmComplete(onboardingToken)
expectState { copy(submitState = OnboardingSubmitState.Loading) }
expectState { copy(submitState = OnboardingSubmitState.Success, step = OnboardingStep.COMPLETE) }
expectSideEffect(OnboardingSideEffect.PermissionRequest)
expectState { copy(isSubmitting = true, step = OnboardingStep.COMPLETE) }
expectState { copy(isSubmitting = false, step = OnboardingStep.COMPLETE) }
}
}

Expand All @@ -169,7 +177,7 @@ class OnboardingViewModelTest {
birthTime = BirthTime.JA,
lifeStage = Job.STUDENT,
relationshipStatus = RelationshipStatus.SOLO,
submitState = OnboardingSubmitState.Loading,
isSubmitting = true,
)
viewModel().test(this, initialState = initial) {
containerHost.confirmComplete(onboardingToken)
Expand All @@ -196,8 +204,8 @@ class OnboardingViewModelTest {
)
viewModel().test(this, initialState = initial) {
containerHost.confirmComplete(onboardingToken)
expectState { copy(submitState = OnboardingSubmitState.Loading) }
expectState { copy(submitState = OnboardingSubmitState.Failure) }
expectState { copy(isSubmitting = true, step = OnboardingStep.COMPLETE) }
expectState { copy(isSubmitting = false, step = OnboardingStep.EXTRA_QUESTION) }
expectSideEffect(OnboardingSideEffect.Failure(error))
}
}
Expand Down
Loading