feat: error handeling
This commit is contained in:
@@ -67,15 +67,11 @@ class DrugRepositoryImpl(
|
|||||||
|
|
||||||
val searchResult = parser.parseSearchResultsWithPagination(htmlResponse)
|
val searchResult = parser.parseSearchResultsWithPagination(htmlResponse)
|
||||||
|
|
||||||
if (searchResult.drugs.isNotEmpty()) {
|
|
||||||
Result.success(searchResult)
|
Result.success(searchResult)
|
||||||
} else {
|
|
||||||
Result.failure(Exception("No drugs found for query: '${params.query}'"))
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
Result.failure(Exception("Network error: ${e.message}", e))
|
Result.failure(e)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Result.failure(Exception("An error occurred: ${e.message}", e))
|
Result.failure(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.approagency.pharmacy.domain.model.DrugDetail
|
import com.approagency.pharmacy.domain.model.DrugDetail
|
||||||
import com.approagency.pharmacy.domain.usecase.DrugDetailYabUseCase
|
import com.approagency.pharmacy.domain.usecase.DrugDetailYabUseCase
|
||||||
|
import com.approagency.pharmacy.utils.toUserMessage
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
@@ -22,7 +23,7 @@ class DrugDetailViewModel(
|
|||||||
val result = drugDetailUseCase(detailUrl)
|
val result = drugDetailUseCase(detailUrl)
|
||||||
_detailState.value = when {
|
_detailState.value = when {
|
||||||
result.isSuccess -> DrugDetailYabState.Success(result.getOrNull()!!)
|
result.isSuccess -> DrugDetailYabState.Success(result.getOrNull()!!)
|
||||||
else -> DrugDetailYabState.Error(result.exceptionOrNull()?.message ?: "خطا در دریافت اطلاعات")
|
else -> DrugDetailYabState.Error(result.exceptionOrNull().toUserMessage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import com.approagency.pharmacy.domain.model.DrugSearchParams
|
|||||||
import com.approagency.pharmacy.domain.usecase.GetDarmanUseCase
|
import com.approagency.pharmacy.domain.usecase.GetDarmanUseCase
|
||||||
import com.approagency.pharmacy.domain.usecase.GetDrugDetailUseCase
|
import com.approagency.pharmacy.domain.usecase.GetDrugDetailUseCase
|
||||||
import com.approagency.pharmacy.domain.usecase.GetDrugSearchUseCase
|
import com.approagency.pharmacy.domain.usecase.GetDrugSearchUseCase
|
||||||
|
import com.approagency.pharmacy.utils.ErrorMessages
|
||||||
|
import com.approagency.pharmacy.utils.toUserMessage
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
@@ -49,9 +51,9 @@ class HomeViewModel (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}catch (e: Exception) {
|
}catch (e: Exception) {
|
||||||
handleError(e.message)
|
handleError(e.toUserMessage())
|
||||||
}catch (e: Exception) {
|
}catch (e: Exception) {
|
||||||
handleError(e.localizedMessage ?: "Unknown error")
|
handleError(e.toUserMessage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,10 +75,10 @@ class HomeViewModel (
|
|||||||
) }
|
) }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
println(e.message)
|
println(e.message)
|
||||||
handleError(e.message)
|
handleError(e.toUserMessage())
|
||||||
}catch (e: Exception) {
|
}catch (e: Exception) {
|
||||||
println(e.message)
|
println(e.message)
|
||||||
handleError(e.localizedMessage ?: "Unknown error")
|
handleError(e.toUserMessage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,9 +105,9 @@ class HomeViewModel (
|
|||||||
}
|
}
|
||||||
println(result)
|
println(result)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
handleError(e.message)
|
handleError(e.toUserMessage())
|
||||||
}catch (e: Exception) {
|
}catch (e: Exception) {
|
||||||
handleError(e.localizedMessage ?: "Unknown error")
|
handleError(e.toUserMessage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +128,7 @@ class HomeViewModel (
|
|||||||
) , drugDetailState = it.drugDetailState.copy(
|
) , drugDetailState = it.drugDetailState.copy(
|
||||||
isLoading = false
|
isLoading = false
|
||||||
)) }
|
)) }
|
||||||
_event.emit(HomeEvent.ShowError(message ?: "Error occurred"))
|
_event.emit(HomeEvent.ShowError(message ?: ErrorMessages.GENERIC))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear error when consumed
|
// Clear error when consumed
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.approagency.pharmacy.domain.model.TestItem
|
|||||||
import com.approagency.pharmacy.domain.usecase.GetTestGroupUseCase
|
import com.approagency.pharmacy.domain.usecase.GetTestGroupUseCase
|
||||||
import com.approagency.pharmacy.domain.usecase.GetTestItemByGroupId
|
import com.approagency.pharmacy.domain.usecase.GetTestItemByGroupId
|
||||||
import com.approagency.pharmacy.domain.usecase.SearchTestsUseCase
|
import com.approagency.pharmacy.domain.usecase.SearchTestsUseCase
|
||||||
|
import com.approagency.pharmacy.utils.toUserMessage
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
@@ -87,7 +88,7 @@ class LabViewModel (
|
|||||||
it.copy(
|
it.copy(
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
searchResults = null,
|
searchResults = null,
|
||||||
error = e.message ?: "خطا در جستجو"
|
error = e.toUserMessage()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +110,7 @@ class LabViewModel (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (e:HttpException){
|
} catch (e:HttpException){
|
||||||
handleError(e.message)
|
handleError(e.toUserMessage())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -132,7 +133,7 @@ class LabViewModel (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (e:HttpException){
|
} catch (e:HttpException){
|
||||||
handleError(e.message)
|
handleError(e.toUserMessage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -7,6 +7,7 @@ import com.approagency.pharmacy.domain.model.PharmacyDetail
|
|||||||
import com.approagency.pharmacy.domain.model.PharmacyItem
|
import com.approagency.pharmacy.domain.model.PharmacyItem
|
||||||
import com.approagency.pharmacy.domain.usecase.GetPharmaciesUseCase
|
import com.approagency.pharmacy.domain.usecase.GetPharmaciesUseCase
|
||||||
import com.approagency.pharmacy.domain.usecase.GetPharmacyDetailUseCase
|
import com.approagency.pharmacy.domain.usecase.GetPharmacyDetailUseCase
|
||||||
|
import com.approagency.pharmacy.utils.toUserMessage
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
@@ -61,7 +62,7 @@ class PharmacyViewModel(
|
|||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
_pharmacyDetailStates.value = _pharmacyDetailStates.value.toMutableMap().apply {
|
_pharmacyDetailStates.value = _pharmacyDetailStates.value.toMutableMap().apply {
|
||||||
put(pharmacyUrl, PharmacyDetailState.Error(e.message ?: "خطا در دریافت اطلاعات"))
|
put(pharmacyUrl, PharmacyDetailState.Error(e.toUserMessage()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,7 +91,7 @@ class PharmacyViewModel(
|
|||||||
val result = getPharmaciesUseCase(genericDrugId, brandIrc, provinceId)
|
val result = getPharmaciesUseCase(genericDrugId, brandIrc, provinceId)
|
||||||
_state.value = PharmacyState.Success(result)
|
_state.value = PharmacyState.Success(result)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
_state.value = PharmacyState.Error(e.message ?: "خطا در دریافت اطلاعات")
|
_state.value = PharmacyState.Error(e.toUserMessage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.approagency.pharmacy.domain.model.DrugSearchResult
|
import com.approagency.pharmacy.domain.model.DrugSearchResult
|
||||||
import com.approagency.pharmacy.domain.usecase.SearchDrugsYabUseCase
|
import com.approagency.pharmacy.domain.usecase.SearchDrugsYabUseCase
|
||||||
|
import com.approagency.pharmacy.utils.toUserMessage
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
@@ -77,7 +78,7 @@ class SearchViewModel(
|
|||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
isLoadingMore = false
|
isLoadingMore = false
|
||||||
SearchState.Error(result.exceptionOrNull()?.message ?: "خطا در جستجو")
|
SearchState.Error(result.exceptionOrNull().toUserMessage())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.approagency.pharmacy.utils
|
||||||
|
|
||||||
|
import retrofit2.HttpException
|
||||||
|
import java.io.IOException
|
||||||
|
import java.net.SocketTimeoutException
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
|
||||||
|
/** پیامهای خطای فارسیِ امن — بدون افشای منبع داده یا متن خام استثناء. */
|
||||||
|
object ErrorMessages {
|
||||||
|
const val NETWORK = "اتصال به اینترنت برقرار نیست. لطفاً اتصال خود را بررسی کرده و دوباره تلاش کنید."
|
||||||
|
const val TIMEOUT = "زمان پاسخگویی به پایان رسید. لطفاً دوباره تلاش کنید."
|
||||||
|
const val SERVER = "در حال حاضر امکان دریافت اطلاعات وجود ندارد. لطفاً کمی بعد دوباره تلاش کنید."
|
||||||
|
const val NOT_FOUND = "موردی یافت نشد."
|
||||||
|
const val GENERIC = "خطایی رخ داد. لطفاً دوباره تلاش کنید."
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* تبدیل استثناء به پیام فارسیِ قابلنمایش به کاربر.
|
||||||
|
* هرگز متن خام استثناء، آدرس سرور یا نام منبع داده را برنمیگرداند.
|
||||||
|
*/
|
||||||
|
fun Throwable?.toUserMessage(): String = when (this) {
|
||||||
|
null -> ErrorMessages.GENERIC
|
||||||
|
is UnknownHostException -> ErrorMessages.NETWORK
|
||||||
|
is SocketTimeoutException -> ErrorMessages.TIMEOUT
|
||||||
|
is HttpException -> ErrorMessages.SERVER
|
||||||
|
is IOException -> ErrorMessages.NETWORK
|
||||||
|
else -> when (cause) {
|
||||||
|
is UnknownHostException -> ErrorMessages.NETWORK
|
||||||
|
is SocketTimeoutException -> ErrorMessages.TIMEOUT
|
||||||
|
is HttpException -> ErrorMessages.SERVER
|
||||||
|
is IOException -> ErrorMessages.NETWORK
|
||||||
|
else -> ErrorMessages.GENERIC
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user