diff --git a/core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorDialogSpec.kt b/core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorDialogSpec.kt index 270ea48e..2d1d9544 100644 --- a/core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorDialogSpec.kt +++ b/core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorDialogSpec.kt @@ -3,6 +3,7 @@ package com.ninecraft.booket.core.common.constants import androidx.annotation.StringRes data class ErrorDialogSpec( + val title: String? = null, val message: String, @StringRes val buttonLabelResId: Int, val action: () -> Unit, diff --git a/core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorScope.kt b/core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorScope.kt index 9fa2c258..bae8788c 100644 --- a/core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorScope.kt +++ b/core/common/src/main/kotlin/com/ninecraft/booket/core/common/constants/ErrorScope.kt @@ -1,5 +1,5 @@ package com.ninecraft.booket.core.common.constants enum class ErrorScope { - GLOBAL, LOGIN, BOOK_REGISTER, RECORD_REGISTER + GLOBAL, LOGIN, AUTH_SESSION_EXPIRED, } diff --git a/core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt b/core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt index ed84d6e8..e8e9ee56 100644 --- a/core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt +++ b/core/common/src/main/kotlin/com/ninecraft/booket/core/common/utils/HandleException.kt @@ -23,7 +23,13 @@ fun handleException( ) { when { exception is HttpException && exception.code() == 401 -> { - onLoginRequired() + postErrorDialog( + errorScope = ErrorScope.AUTH_SESSION_EXPIRED, + exception = exception, + action = { + onLoginRequired() + }, + ) } exception is HttpException -> { @@ -51,53 +57,40 @@ fun postErrorDialog( @StringRes buttonLabelResId: Int = R.string.confirm, action: () -> Unit = {}, ) { - val spec = buildDialog( - scope = errorScope, - exception = exception, - buttonLabelResId = buttonLabelResId, - action = action, - ) - - ErrorEventHelper.sendError(event = ErrorEvent.ShowDialog(spec)) -} - -private fun buildDialog( - scope: ErrorScope, - exception: Throwable, - @StringRes buttonLabelResId: Int, - action: () -> Unit, -): ErrorDialogSpec { - val message = when { + val (title, message) = when { exception.isNetworkError() -> { - "네트워크 연결이 불안정합니다.\n인터넷 연결을 확인해주세요" + null to "네트워크 연결이 불안정합니다.\n인터넷 연결을 확인해주세요" } exception is HttpException -> { - when (scope) { + when (errorScope) { ErrorScope.GLOBAL -> { - "알 수 없는 문제가 발생했어요.\n다시 시도해주세요" + null to "알 수 없는 문제가 발생했어요.\n다시 시도해주세요" } ErrorScope.LOGIN -> { - "예기치 않은 오류가 발생했습니다.\n다시 로그인 해주세요." + "로그인 오류" to "예기치 않은 오류가 발생했습니다.\n다시 로그인 해주세요." } - ErrorScope.BOOK_REGISTER -> { - "도서 등록 중 오류가 발생했어요.\n다시 시도해주세요" - } - - ErrorScope.RECORD_REGISTER -> { - "기록 저장에 실패했어요.\n다시 시도해주세요" + ErrorScope.AUTH_SESSION_EXPIRED -> { + null to "세션이 만료되었어요.\n다시 로그인 해주세요" } } } else -> { - "알 수 없는 문제가 발생했어요.\n다시 시도해주세요" + null to "알 수 없는 문제가 발생했어요.\n다시 시도해주세요" } } - return ErrorDialogSpec(message = message, buttonLabelResId = buttonLabelResId, action = action) + val spec = ErrorDialogSpec( + title = title, + message = message, + buttonLabelResId = buttonLabelResId, + action = action, + ) + + ErrorEventHelper.sendError(event = ErrorEvent.ShowDialog(spec)) } @Suppress("TooGenericExceptionCaught") diff --git a/feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt b/feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt index 3bfb3f5c..f587d82c 100644 --- a/feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt +++ b/feature/home/src/main/kotlin/com/ninecraft/booket/feature/home/HomePresenter.kt @@ -6,6 +6,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import com.ninecraft.booket.core.common.analytics.AnalyticsHelper +import com.ninecraft.booket.core.common.utils.handleException import com.ninecraft.booket.core.data.api.repository.AuthRepository import com.ninecraft.booket.core.data.api.repository.BookRepository import com.ninecraft.booket.core.model.RecentBookModel @@ -13,6 +14,7 @@ import com.ninecraft.booket.core.model.UserState import com.ninecraft.booket.feature.screens.BookDetailScreen import com.ninecraft.booket.feature.screens.BookSearchScreen import com.ninecraft.booket.feature.screens.HomeScreen +import com.ninecraft.booket.feature.screens.LoginScreen import com.ninecraft.booket.feature.screens.RecordScreen import com.ninecraft.booket.feature.screens.SettingsScreen import com.skydoves.compose.effects.RememberedEffect @@ -56,6 +58,14 @@ class HomePresenter @AssistedInject constructor( recentBooks = result.recentBooks.toPersistentList() }.onFailure { exception -> uiState = UiState.Error(exception) + + handleException( + exception = exception, + onError = {}, + onLoginRequired = { + navigator.resetRoot(LoginScreen()) + }, + ) } } } diff --git a/feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt b/feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt index 712d21d0..c49b0106 100644 --- a/feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt +++ b/feature/library/src/main/kotlin/com/ninecraft/booket/feature/library/LibraryPresenter.kt @@ -8,6 +8,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import com.ninecraft.booket.core.common.analytics.AnalyticsHelper import com.ninecraft.booket.core.common.utils.UiText +import com.ninecraft.booket.core.common.utils.handleException import com.ninecraft.booket.core.data.api.repository.AuthRepository import com.ninecraft.booket.core.data.api.repository.BookRepository import com.ninecraft.booket.core.model.LibraryBookSummaryModel @@ -16,6 +17,7 @@ import com.ninecraft.booket.core.ui.component.FooterState import com.ninecraft.booket.feature.screens.BookDetailScreen import com.ninecraft.booket.feature.screens.LibraryScreen import com.ninecraft.booket.feature.screens.LibrarySearchScreen +import com.ninecraft.booket.feature.screens.LoginScreen import com.ninecraft.booket.feature.screens.SettingsScreen import com.ninecraft.booket.feature.screens.extensions.redirectToLogin import com.orhanobut.logger.Logger @@ -105,6 +107,14 @@ class LibraryPresenter @AssistedInject constructor( } else { footerState = FooterState.Error(errorMessage) } + + handleException( + exception = exception, + onError = {}, + onLoginRequired = { + navigator.resetRoot(LoginScreen()) + }, + ) } } } @@ -136,7 +146,10 @@ class LibraryPresenter @AssistedInject constructor( } currentFilter = event.filterOption - filterLibraryBooks(status = currentFilter.getApiValue(), page = START_INDEX, size = PAGE_SIZE) + + if (userState !is UserState.Guest) { + filterLibraryBooks(status = currentFilter.getApiValue(), page = START_INDEX, size = PAGE_SIZE) + } } is LibraryUiEvent.OnBookClick -> { diff --git a/feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt b/feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt index 34917f4e..8eb0bfc2 100644 --- a/feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt +++ b/feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginPresenter.kt @@ -6,6 +6,8 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import com.ninecraft.booket.core.common.analytics.AnalyticsHelper +import com.ninecraft.booket.core.common.constants.ErrorScope +import com.ninecraft.booket.core.common.utils.postErrorDialog import com.ninecraft.booket.core.data.api.repository.AuthRepository import com.ninecraft.booket.core.data.api.repository.UserRepository import com.ninecraft.booket.feature.screens.HomeScreen @@ -60,10 +62,11 @@ class LoginPresenter @AssistedInject constructor( } } }.onFailure { exception -> - exception.message?.let { Logger.e(it) } - sideEffect = exception.message?.let { - LoginSideEffect.ShowToast(it) - } + Logger.e(exception.message ?: "Failed to get user profile") + postErrorDialog( + errorScope = ErrorScope.LOGIN, + exception = exception, + ) } } } @@ -72,7 +75,7 @@ class LoginPresenter @AssistedInject constructor( when (event) { is LoginUiEvent.OnKakaoLoginButtonClick -> { isLoading = true - sideEffect = LoginSideEffect.KakaoLogin + sideEffect = LoginSideEffect.KakaoLogin() } is LoginUiEvent.LoginFailure -> { @@ -89,11 +92,12 @@ class LoginPresenter @AssistedInject constructor( .onSuccess { navigateAfterLogin() }.onFailure { exception -> - exception.message?.let { Logger.e(it) } + Logger.e(exception.message ?: "Login failed") analyticsHelper.logEvent(EVENT_ERROR_LOGIN) - sideEffect = exception.message?.let { - LoginSideEffect.ShowToast(it) - } + postErrorDialog( + errorScope = ErrorScope.LOGIN, + exception = exception, + ) } } finally { isLoading = false diff --git a/feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUiState.kt b/feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUiState.kt index 731e2bcb..1f58e248 100644 --- a/feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUiState.kt +++ b/feature/login/src/main/kotlin/com/ninecraft/booket/feature/login/LoginUiState.kt @@ -15,7 +15,7 @@ data class LoginUiState( @Immutable sealed interface LoginSideEffect { - data object KakaoLogin : LoginSideEffect + data class KakaoLogin(private val key: String = UUID.randomUUID().toString()) : LoginSideEffect data class ShowToast( val message: String, private val key: String = UUID.randomUUID().toString(), diff --git a/feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/MainActivity.kt b/feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/MainActivity.kt index 93ad9fcc..b1d44684 100644 --- a/feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/MainActivity.kt +++ b/feature/main/src/main/kotlin/com/ninecraft/booket/feature/main/MainActivity.kt @@ -70,6 +70,7 @@ class MainActivity : ComponentActivity() { dialogSpec.value?.let { spec -> ReedDialog( + title = spec.title, description = spec.message, confirmButtonText = stringResource(spec.buttonLabelResId),