diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/ArtistDetailFragment.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/ArtistDetailFragment.kt index ebbaee48f..b8f361e4a 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/ArtistDetailFragment.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/ArtistDetailFragment.kt @@ -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) { @@ -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( diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/ArtistDetailViewModel.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/ArtistDetailViewModel.kt index d08374588..d5352f7e3 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/ArtistDetailViewModel.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/ArtistDetailViewModel.kt @@ -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 @@ -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 = MutableSharedFlow() val event: SharedFlow = _event.asSharedFlow() @@ -44,7 +47,7 @@ class ArtistDetailViewModel @Inject constructor( festivalPage.isLastPage ) }.onFailure { - _uiState.value = ArtistDetailUiState.Error + handleFailure(key = KEY_LOAD_ARTIST_DETAIL, throwable = it) } } } @@ -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, @@ -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" + } } diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/uistate/ArtistDetailUiState.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/uistate/ArtistDetailUiState.kt index c3188686c..2998f978a 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/uistate/ArtistDetailUiState.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/artistdetail/uistate/ArtistDetailUiState.kt @@ -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, 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 diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/FestivalDetailFragment.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/FestivalDetailFragment.kt index 881d2f341..8f400c85d 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/FestivalDetailFragment.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/FestivalDetailFragment.kt @@ -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) } } @@ -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 -> { diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/FestivalDetailViewModel.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/FestivalDetailViewModel.kt index e21dfd66f..168e50620 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/FestivalDetailViewModel.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/FestivalDetailViewModel.kt @@ -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(), diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/uiState/FestivalDetailUiState.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/uiState/FestivalDetailUiState.kt index dc0f2eb1c..4e4953457 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/uiState/FestivalDetailUiState.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/festivaldetail/uiState/FestivalDetailUiState.kt @@ -8,7 +8,7 @@ interface FestivalDetailUiState { val stages: List, ) : 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() diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/FestivalListFragment.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/FestivalListFragment.kt index 2d2c7b15a..2aeea5f3e 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/FestivalListFragment.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/FestivalListFragment.kt @@ -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) } } @@ -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 diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/FestivalListViewModel.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/FestivalListViewModel.kt index 6a380b740..ab23ccbe0 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/FestivalListViewModel.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/FestivalListViewModel.kt @@ -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) } } } @@ -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, @@ -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" } } diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/uistate/FestivalListUiState.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/uistate/FestivalListUiState.kt index ec4645d27..b555eeac8 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/uistate/FestivalListUiState.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/home/festivallist/uistate/FestivalListUiState.kt @@ -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 diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/SchoolDetailFragment.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/SchoolDetailFragment.kt index 8ba0df070..81e170e46 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/SchoolDetailFragment.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/SchoolDetailFragment.kt @@ -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) } } @@ -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( diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/SchoolDetailViewModel.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/SchoolDetailViewModel.kt index a295ca2d6..0b327f163 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/SchoolDetailViewModel.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/SchoolDetailViewModel.kt @@ -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) } } } @@ -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, @@ -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" } } diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/uistate/SchoolDetailUiState.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/uistate/SchoolDetailUiState.kt index a996dc3b4..8d23053e0 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/uistate/SchoolDetailUiState.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/schooldetail/uistate/SchoolDetailUiState.kt @@ -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 diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/SearchFragment.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/SearchFragment.kt index 069511de6..7c68a8e78 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/SearchFragment.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/SearchFragment.kt @@ -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) } } @@ -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) diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/SearchViewModel.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/SearchViewModel.kt index 74a950c19..cdaea1dd5 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/SearchViewModel.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/SearchViewModel.kt @@ -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(), diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/uistate/SearchUiState.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/uistate/SearchUiState.kt index d80d392f2..09b7e3956 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/uistate/SearchUiState.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/uistate/SearchUiState.kt @@ -13,7 +13,7 @@ sealed interface SearchUiState { val searchedSchools: List, ) : 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() diff --git a/android/festago/presentation/src/main/res/layout/fragment_artist_detail.xml b/android/festago/presentation/src/main/res/layout/fragment_artist_detail.xml index 7423633de..c1ec166d5 100644 --- a/android/festago/presentation/src/main/res/layout/fragment_artist_detail.xml +++ b/android/festago/presentation/src/main/res/layout/fragment_artist_detail.xml @@ -12,6 +12,10 @@ + + @@ -169,6 +173,11 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + - diff --git a/android/festago/presentation/src/main/res/layout/fragment_festival_detail.xml b/android/festago/presentation/src/main/res/layout/fragment_festival_detail.xml index e5b1968ec..656603ec4 100644 --- a/android/festago/presentation/src/main/res/layout/fragment_festival_detail.xml +++ b/android/festago/presentation/src/main/res/layout/fragment_festival_detail.xml @@ -16,6 +16,10 @@ + + + + diff --git a/android/festago/presentation/src/main/res/layout/fragment_festival_list.xml b/android/festago/presentation/src/main/res/layout/fragment_festival_list.xml index 84d363c1d..8332ffd0d 100644 --- a/android/festago/presentation/src/main/res/layout/fragment_festival_list.xml +++ b/android/festago/presentation/src/main/res/layout/fragment_festival_list.xml @@ -8,6 +8,10 @@ + + + + diff --git a/android/festago/presentation/src/main/res/layout/fragment_school_detail.xml b/android/festago/presentation/src/main/res/layout/fragment_school_detail.xml index 53aa2444d..65dd6d469 100644 --- a/android/festago/presentation/src/main/res/layout/fragment_school_detail.xml +++ b/android/festago/presentation/src/main/res/layout/fragment_school_detail.xml @@ -12,6 +12,10 @@ + + + diff --git a/android/festago/presentation/src/main/res/layout/fragment_search.xml b/android/festago/presentation/src/main/res/layout/fragment_search.xml index 3ad2f2c5b..1bcfbe239 100644 --- a/android/festago/presentation/src/main/res/layout/fragment_search.xml +++ b/android/festago/presentation/src/main/res/layout/fragment_search.xml @@ -8,6 +8,10 @@ + + +