Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AN/USER] feat: 에러 화면, 새로고침 적용 (#898) #899

Merged
merged 6 commits into from
Apr 29, 2024
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 @@ -73,11 +73,9 @@ class ArtistDetailFragment : Fragment() {
}

private fun updateUi(uiState: ArtistDetailUiState) = when (uiState) {
is ArtistDetailUiState.Loading,
is ArtistDetailUiState.Error,
-> Unit

is ArtistDetailUiState.Loading -> Unit
is ArtistDetailUiState.Success -> handleSuccess(uiState)
is ArtistDetailUiState.Error -> handleError(uiState)
}

private fun handleSuccess(uiState: ArtistDetailUiState.Success) {
Expand All @@ -101,6 +99,10 @@ class ArtistDetailFragment : Fragment() {
}
}

private fun handleError(uiState: ArtistDetailUiState.Error) {
binding.refreshListener = { uiState.refresh(args.artistId) }
}

private fun handleEvent(event: ArtistDetailEvent) = when (event) {
is ArtistDetailEvent.ShowArtistDetail -> {
findNavController().navigate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.festago.festago.presentation.ui.artistdetail

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.festago.festago.common.analytics.AnalyticsHelper
import com.festago.festago.common.analytics.logNetworkFailure
import com.festago.festago.domain.model.festival.FestivalsPage
import com.festago.festago.domain.repository.ArtistRepository
import com.festago.festago.presentation.ui.artistdetail.uistate.ArtistDetailUiState
Expand All @@ -21,6 +23,7 @@ import javax.inject.Inject
@HiltViewModel
class ArtistDetailViewModel @Inject constructor(
private val artistRepository: ArtistRepository,
private val analyticsHelper: AnalyticsHelper,
) : ViewModel() {
private val _event: MutableSharedFlow<ArtistDetailEvent> = MutableSharedFlow()
val event: SharedFlow<ArtistDetailEvent> = _event.asSharedFlow()
Expand All @@ -44,7 +47,7 @@ class ArtistDetailViewModel @Inject constructor(
festivalPage.isLastPage
)
}.onFailure {
_uiState.value = ArtistDetailUiState.Error
handleFailure(key = KEY_LOAD_ARTIST_DETAIL, throwable = it)
}
}
}
Expand All @@ -64,10 +67,23 @@ class ArtistDetailViewModel @Inject constructor(
festivals = currentFestivals + festivalsPage.toUiState(),
isLast = festivalsPage.isLastPage
)
}.onFailure {
handleFailure(key = KEY_LOAD_MORE_ARTIST_FESTIVAL, throwable = it)
}
}
}

private fun handleFailure(key: String, throwable: Throwable) {
_uiState.value = ArtistDetailUiState.Error {
_uiState.value = ArtistDetailUiState.Loading
loadArtistDetail(it)
}
analyticsHelper.logNetworkFailure(
key = key,
value = throwable.message.toString()
)
}

private fun FestivalsPage.toUiState() = festivals.map {
FestivalItemUiState(
id = it.id,
Expand All @@ -94,4 +110,9 @@ class ArtistDetailViewModel @Inject constructor(
},
)
}

companion object {
private const val KEY_LOAD_ARTIST_DETAIL = "KEY_LOAD_ARTIST_DETAIL"
private const val KEY_LOAD_MORE_ARTIST_FESTIVAL = "KEY_LOAD_MORE_ARTIST_FESTIVAL"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import com.festago.festago.domain.model.artist.ArtistDetail
sealed interface ArtistDetailUiState {
object Loading : ArtistDetailUiState

object Error : ArtistDetailUiState

data class Success(
val artist: ArtistDetail,
val festivals: List<FestivalItemUiState>,
val isLast: Boolean,
) : ArtistDetailUiState

class Error(val refresh: (id: Long) -> Unit) : ArtistDetailUiState

val shouldShowSuccess get() = this is Success
val shouldShowEmptyFestivals get() = this is Success && festivals.isEmpty()
val shouldShowLoading get() = this is Loading
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,9 @@ class FestivalDetailFragment : Fragment() {

private fun updateUi(uiState: FestivalDetailUiState) {
when (uiState) {
is FestivalDetailUiState.Loading,
is FestivalDetailUiState.Error,
-> Unit

is FestivalDetailUiState.Loading -> Unit
is FestivalDetailUiState.Success -> handleSuccess(uiState)
is FestivalDetailUiState.Error -> handleError(uiState)
}
}

Expand All @@ -100,6 +98,10 @@ class FestivalDetailFragment : Fragment() {
}
}

private fun handleError(uiState: FestivalDetailUiState.Error) {
binding.refreshListener = { uiState.refresh(args.festivalId) }
}

private fun TextView.setFestivalDDay(startDate: LocalDate, endDate: LocalDate) {
when {
LocalDate.now() in startDate..endDate -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ class FestivalDetailViewModel @Inject constructor(
festivalRepository.loadFestivalDetail(festivalId).onSuccess { festivalDetail ->
_uiState.value = festivalDetail.toSuccessUiState()
}.onFailure {
_uiState.value = FestivalDetailUiState.Error
_uiState.value = FestivalDetailUiState.Error { festivalId ->
_uiState.value = FestivalDetailUiState.Loading
loadFestivalDetail(festivalId)
}
analyticsHelper.logNetworkFailure(
key = KEY_LOAD_FESTIVAL_DETAIL,
value = it.message.toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface FestivalDetailUiState {
val stages: List<StageItemUiState>,
) : FestivalDetailUiState

object Error : FestivalDetailUiState
class Error(val refresh: (id: Long) -> Unit) : FestivalDetailUiState

val shouldShowSuccess get() = this is Success
val shouldShowEmptyStages get() = shouldShowSuccess && (this as Success).stages.isEmpty()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,9 @@ class FestivalListFragment : Fragment() {

private fun updateUi(uiState: FestivalListUiState) {
when (uiState) {
is FestivalListUiState.Loading,
is FestivalListUiState.Error,
-> Unit

is FestivalListUiState.Loading -> Unit
is FestivalListUiState.Success -> handleSuccess(uiState)
is FestivalListUiState.Error -> handleError(uiState)
}
}

Expand Down Expand Up @@ -185,6 +183,10 @@ class FestivalListFragment : Fragment() {
}.toList()
}

private fun handleError(uiState: FestivalListUiState.Error) {
binding.refreshListener = uiState.refresh
}

private fun requestMoreFestival() {
val festivalListUiState = vm.uiState.value as? FestivalListUiState.Success ?: return
if (festivalListUiState.isLastPage) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ class FestivalListViewModel @Inject constructor(
schoolRegion = schoolRegion,
)
}.onFailure {
_uiState.value = FestivalListUiState.Error
analyticsHelper.logNetworkFailure(
key = KEY_LOAD_FESTIVAL,
value = it.message.toString(),
)
handleFailure(key = KEY_INIT_FESTIVALS, throwable = it)
}
}
}
Expand Down Expand Up @@ -108,10 +104,23 @@ class FestivalListViewModel @Inject constructor(
schoolRegion = schoolRegion,
isLastPage = festivalsPage.isLastPage,
)
}.onFailure {
handleFailure(key = KEY_LOAD_FESTIVALS, throwable = it)
}
}
}

private fun handleFailure(key: String, throwable: Throwable) {
_uiState.value = FestivalListUiState.Error {
_uiState.value = FestivalListUiState.Loading
initFestivalList()
}
analyticsHelper.logNetworkFailure(
key = key,
value = throwable.message.toString(),
)
}

private fun updateFestivalsState(
festivalFilterUiState: FestivalFilterUiState?,
successUiState: FestivalListUiState.Success,
Expand Down Expand Up @@ -164,6 +173,7 @@ class FestivalListViewModel @Inject constructor(
}

companion object {
private const val KEY_LOAD_FESTIVAL = "KEY_LOAD_FESTIVAL"
private const val KEY_INIT_FESTIVALS = "KEY_INIT_FESTIVALS"
private const val KEY_LOAD_FESTIVALS = "KEY_LOAD_FESTIVALS"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ sealed interface FestivalListUiState {
val schoolRegion: SchoolRegion? = null,
) : FestivalListUiState

object Error : FestivalListUiState
class Error(val refresh: () -> Unit) : FestivalListUiState

val shouldShowSuccess get() = this is Success
val shouldShowLoading get() = this is Loading
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,9 @@ class SchoolDetailFragment : Fragment() {

private fun updateUi(uiState: SchoolDetailUiState) {
when (uiState) {
is SchoolDetailUiState.Loading,
is SchoolDetailUiState.Error,
-> Unit

is SchoolDetailUiState.Loading -> Unit
is SchoolDetailUiState.Success -> handleSuccess(uiState)
is SchoolDetailUiState.Error -> handleError(uiState)
}
}

Expand All @@ -103,6 +101,10 @@ class SchoolDetailFragment : Fragment() {
}
}

private fun handleError(uiState: SchoolDetailUiState.Error) {
binding.refreshListener = { uiState.refresh(args.schoolId) }
}

private fun handleEvent(event: SchoolDetailEvent) = when (event) {
is SchoolDetailEvent.ShowArtistDetail -> {
findNavController().navigate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ class SchoolDetailViewModel @Inject constructor(
isLast = festivalPage.isLastPage,
)
}.onFailure {
_uiState.value = SchoolDetailUiState.Error
analyticsHelper.logNetworkFailure(
key = KEY_LOAD_SCHOOL_DETAIL,
value = it.message.toString(),
)
handleFailure(key = KEY_LOAD_SCHOOL_DETAIL, throwable = it)
}
}
}
Expand All @@ -71,10 +67,23 @@ class SchoolDetailViewModel @Inject constructor(
festivals = currentFestivals + festivalsPage.festivals.map { it.toUiState() },
isLast = festivalsPage.isLastPage
)
}.onFailure {
handleFailure(key = KEY_LOAD_MORE_SCHOOL_FESTIVALS, throwable = it)
}
}
}

private fun handleFailure(key: String, throwable: Throwable) {
_uiState.value = SchoolDetailUiState.Error {
_uiState.value = SchoolDetailUiState.Loading
loadSchoolDetail(it)
}
analyticsHelper.logNetworkFailure(
key = key,
value = throwable.message.toString()
)
}

private fun Festival.toUiState() = FestivalItemUiState(
id = id,
name = name,
Expand Down Expand Up @@ -102,5 +111,6 @@ class SchoolDetailViewModel @Inject constructor(

companion object {
private const val KEY_LOAD_SCHOOL_DETAIL = "KEY_LOAD_SCHOOL_DETAIL"
private const val KEY_LOAD_MORE_SCHOOL_FESTIVALS = "KEY_LOAD_MORE_SCHOOL_FESTIVALS"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ sealed interface SchoolDetailUiState {
val isLast: Boolean,
) : SchoolDetailUiState

object Error : SchoolDetailUiState
class Error(val refresh: (schoolId: Long) -> Unit) : SchoolDetailUiState

val shouldShowSuccess get() = this is Success
val shouldShowLoading get() = this is Loading
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,10 @@ class SearchFragment : Fragment() {

private fun updateUi(uiState: SearchUiState) {
when (uiState) {
is SearchUiState.Loading,
is SearchUiState.Error,
-> Unit

is SearchUiState.Loading -> Unit
is SearchUiState.RecentSearchSuccess -> handleRecentSearchSuccess(uiState)
is SearchUiState.SearchSuccess -> handleSuccessSearch(uiState)
is SearchUiState.Error -> handleError(uiState)
}
}

Expand Down Expand Up @@ -162,6 +160,10 @@ class SearchFragment : Fragment() {
initSearchTab()
}

private fun handleError(uiState: SearchUiState.Error) {
binding.refreshListener = { uiState.refresh.invoke(binding.etSearch.text.toString()) }
}

private fun initSearchTab() {
binding.vpSearch.doOnNextLayout {
binding.vpSearch.setCurrentItem(vm.currentScreen.screenPosition, false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ class SearchViewModel @Inject constructor(
deferredSchools.await().getOrThrow().map { it.toUiState() },
)
}.onFailure {
_uiState.value = SearchUiState.Error
_uiState.value = SearchUiState.Error { searchQuery ->
_uiState.value = SearchUiState.Loading
search(searchQuery)
}
analyticsHelper.logNetworkFailure(
key = KEY_SEARCH,
value = it.message.toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ sealed interface SearchUiState {
val searchedSchools: List<SchoolSearchItemUiState>,
) : SearchUiState

object Error : SearchUiState
class Error(val refresh: (searchQuery: String) -> Unit) : SearchUiState

val shouldShowNotEmptyRecentSearchSuccess get() = this is RecentSearchSuccess && recentSearchQueries.isNotEmpty()
val shouldShowEmptyRecentSearchSuccess get() = this is RecentSearchSuccess && recentSearchQueries.isEmpty()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
<variable
name="successUiState"
type="com.festago.festago.presentation.ui.artistdetail.uistate.ArtistDetailUiState.Success" />

<variable
name="refreshListener"
type="kotlin.jvm.functions.Function0" />
</data>


Expand Down Expand Up @@ -169,6 +173,11 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<include
android:id="@+id/errorLayout"
layout="@layout/layout_network_error"
refreshListener="@{refreshListener}"
visibility="@{uiState.shouldShowError}" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
<variable
name="successUiState"
type="com.festago.festago.presentation.ui.festivaldetail.uiState.FestivalDetailUiState.Success" />

<variable
name="refreshListener"
type="kotlin.jvm.functions.Function0" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
Expand Down Expand Up @@ -234,5 +238,11 @@
app:layout_constraintTop_toTopOf="parent"
app:visibility="@{uiState.shouldShowEmptyStages}" />

<include
android:id="@+id/errorLayout"
layout="@layout/layout_network_error"
refreshListener="@{refreshListener}"
visibility="@{uiState.shouldShowError}" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Loading
Loading