diff --git a/android/festago/data/src/main/java/com/festago/festago/data/util/ResponseExt.kt b/android/festago/data/src/main/java/com/festago/festago/data/util/ResponseExt.kt index bb0466454..a44604558 100644 --- a/android/festago/data/src/main/java/com/festago/festago/data/util/ResponseExt.kt +++ b/android/festago/data/src/main/java/com/festago/festago/data/util/ResponseExt.kt @@ -1,7 +1,10 @@ package com.festago.festago.data.util +import com.festago.festago.domain.exception.BookmarkLimitExceededException +import com.festago.festago.domain.exception.NetworkException import com.festago.festago.domain.exception.UnauthorizedException import retrofit2.Response +import java.net.UnknownHostException suspend fun runCatchingResponse( block: suspend () -> Response, @@ -12,9 +15,9 @@ suspend fun runCatchingResponse( return Result.success(response.body()!!) } - if (response.code() == 401) { - throw UnauthorizedException() - } + handleUnauthorizedException(response) + + handleBadRequestException(response) return Result.failure( Throwable( @@ -26,6 +29,26 @@ suspend fun runCatchingResponse( ), ) } catch (e: Exception) { + if (e is UnknownHostException) { + return Result.failure(NetworkException()) + } return Result.failure(e) } } + +private fun handleUnauthorizedException(response: Response) { + if (response.code() == 401) { + throw UnauthorizedException() + } +} + +private fun handleBadRequestException(response: Response) { + if (response.code() == 400) { + response.errorBody()?.string()?.let { + if (it.contains("BOOKMARK_LIMIT_EXCEEDED")) { + throw BookmarkLimitExceededException() + } + } + throw Throwable("400 Bad Request") + } +} diff --git a/android/festago/domain/src/main/java/com/festago/festago/domain/exception/BookmarkLimitExeededException.kt b/android/festago/domain/src/main/java/com/festago/festago/domain/exception/BookmarkLimitExeededException.kt new file mode 100644 index 000000000..94e30c942 --- /dev/null +++ b/android/festago/domain/src/main/java/com/festago/festago/domain/exception/BookmarkLimitExeededException.kt @@ -0,0 +1,5 @@ +package com.festago.festago.domain.exception + +class BookmarkLimitExceededException : Exception() + +fun Throwable.isBookmarkLimitExceeded() = this is BookmarkLimitExceededException diff --git a/android/festago/domain/src/main/java/com/festago/festago/domain/exception/NetworkException.kt b/android/festago/domain/src/main/java/com/festago/festago/domain/exception/NetworkException.kt new file mode 100644 index 000000000..c85c57236 --- /dev/null +++ b/android/festago/domain/src/main/java/com/festago/festago/domain/exception/NetworkException.kt @@ -0,0 +1,4 @@ +package com.festago.festago.domain.exception + +class NetworkException : Exception() +fun Throwable.isNetworkError() = this is NetworkException 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 091935f53..b1f479db7 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 @@ -4,6 +4,9 @@ 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.exception.isBookmarkLimitExceeded +import com.festago.festago.domain.exception.isNetworkError +import com.festago.festago.domain.exception.isUnauthorized import com.festago.festago.domain.model.bookmark.BookmarkType import com.festago.festago.domain.model.festival.FestivalsPage import com.festago.festago.domain.repository.ArtistRepository @@ -108,26 +111,35 @@ class ArtistDetailViewModel @Inject constructor( viewModelScope.launch { val uiState = uiState.value as? ArtistDetailUiState.Success ?: return@launch - if (!userRepository.isSigned()) { - _event.emit(BookmarkFailure("로그인이 필요합니다")) - return@launch - } - if (uiState.bookMarked) { _uiState.value = uiState.copy(bookMarked = false) bookmarkRepository.deleteArtistBookmark(artistId.toLong()) .onSuccess { _event.emit(BookmarkSuccess(false)) } .onFailure { - _uiState.value = uiState.copy(bookMarked = true) - _event.emit(BookmarkFailure("북마크를 해제할 수 없습니다. 인터넷 연결을 확인해주세요")) + if (it.isUnauthorized()) { + _event.emit(BookmarkFailure("로그인이 필요해요")) + } + if (it.isNetworkError()) { + _uiState.value = uiState.copy(bookMarked = true) + _event.emit(BookmarkFailure("인터넷 연결을 확인해주세요")) + } } } else { _uiState.value = uiState.copy(bookMarked = true) bookmarkRepository.addArtistBookmark(artistId.toLong()) .onSuccess { _event.emit(BookmarkSuccess(true)) } .onFailure { - _uiState.value = uiState.copy(bookMarked = false) - _event.emit(BookmarkFailure("다른 북마크를 해제하거나 인터넷 연결을 확인해주세요")) + if (it.isUnauthorized()) { + _event.emit(BookmarkFailure("로그인이 필요해요")) + } + if (it.isBookmarkLimitExceeded()) { + _uiState.value = uiState.copy(bookMarked = false) + _event.emit(BookmarkFailure("북마크는 12개까지 가능해요")) + } + if (it.isNetworkError()) { + _uiState.value = uiState.copy(bookMarked = false) + _event.emit(BookmarkFailure("인터넷 연결을 확인해주세요")) + } } } } 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 a24cd6dce..7ed86340a 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 @@ -4,6 +4,9 @@ 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.exception.isBookmarkLimitExceeded +import com.festago.festago.domain.exception.isNetworkError +import com.festago.festago.domain.exception.isUnauthorized import com.festago.festago.domain.model.artist.Artist import com.festago.festago.domain.model.bookmark.BookmarkType import com.festago.festago.domain.model.festival.FestivalDetail @@ -96,26 +99,35 @@ class FestivalDetailViewModel @Inject constructor( viewModelScope.launch { val uiState = _uiState.value as? FestivalDetailUiState.Success ?: return@launch - if (!userRepository.isSigned()) { - _event.emit(BookmarkFailure("로그인이 필요합니다")) - return@launch - } - if (uiState.bookmarked) { _uiState.value = uiState.copy(bookmarked = false) bookmarkRepository.deleteFestivalBookmark(festivalId) .onSuccess { _event.emit(BookmarkSuccess(false)) } .onFailure { - _uiState.value = uiState.copy(bookmarked = true) - _event.emit(BookmarkFailure("북마크를 해제할 수 없습니다. 인터넷 연결을 확인해주세요")) + if (it.isUnauthorized()) { + _event.emit(BookmarkFailure("로그인이 필요해요")) + } + if (it.isNetworkError()) { + _uiState.value = uiState.copy(bookmarked = true) + _event.emit(BookmarkFailure("인터넷 연결을 확인해주세요")) + } } } else { _uiState.value = uiState.copy(bookmarked = true) bookmarkRepository.addFestivalBookmark(festivalId) .onSuccess { _event.emit(BookmarkSuccess(true)) } .onFailure { - _uiState.value = uiState.copy(bookmarked = false) - _event.emit(BookmarkFailure("다른 북마크를 해제하거나 인터넷 연결을 확인해주세요")) + if (it.isUnauthorized()) { + _event.emit(BookmarkFailure("로그인이 필요해요")) + } + if (it.isBookmarkLimitExceeded()) { + _uiState.value = uiState.copy(bookmarked = false) + _event.emit(BookmarkFailure("북마크는 12개까지 가능해요")) + } + if (it.isNetworkError()) { + _uiState.value = uiState.copy(bookmarked = false) + _event.emit(BookmarkFailure("인터넷 연결을 확인해주세요")) + } } } } 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 379a3edd2..514111ec0 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 @@ -4,6 +4,9 @@ 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.exception.isBookmarkLimitExceeded +import com.festago.festago.domain.exception.isNetworkError +import com.festago.festago.domain.exception.isUnauthorized import com.festago.festago.domain.model.bookmark.BookmarkType import com.festago.festago.domain.model.festival.Festival import com.festago.festago.domain.repository.BookmarkRepository @@ -106,25 +109,35 @@ class SchoolDetailViewModel @Inject constructor( val uiState = uiState.value as? SchoolDetailUiState.Success ?: return viewModelScope.launch { - if (!userRepository.isSigned()) { - _event.emit(BookmarkFailure("로그인이 필요합니다")) - return@launch - } if (uiState.bookmarked) { _uiState.value = uiState.copy(bookmarked = false) bookmarkRepository.deleteSchoolBookmark(schoolId.toLong()) .onSuccess { _event.emit(BookmarkSuccess(false)) } .onFailure { - _uiState.value = uiState.copy(bookmarked = true) - _event.emit(BookmarkFailure("북마크를 해제할 수 없습니다. 인터넷 연결을 확인해주세요")) + if (it.isUnauthorized()) { + _event.emit(BookmarkFailure("로그인이 필요해요")) + } + if (it.isNetworkError()) { + _uiState.value = uiState.copy(bookmarked = true) + _event.emit(BookmarkFailure("인터넷 연결을 확인해주세요")) + } } } else { _uiState.value = uiState.copy(bookmarked = true) bookmarkRepository.addSchoolBookmark(uiState.schoolInfo.id.toLong()) .onSuccess { _event.emit(BookmarkSuccess(true)) } .onFailure { - _uiState.value = uiState.copy(bookmarked = false) - _event.emit(BookmarkFailure("다른 북마크를 해제하거나 인터넷 연결을 확인해주세요")) + if (it.isUnauthorized()) { + _event.emit(BookmarkFailure("로그인이 필요해요")) + } + if (it.isBookmarkLimitExceeded()) { + _uiState.value = uiState.copy(bookmarked = false) + _event.emit(BookmarkFailure("북마크는 12개까지 가능해요")) + } + if (it.isNetworkError()) { + _uiState.value = uiState.copy(bookmarked = false) + _event.emit(BookmarkFailure("인터넷 연결을 확인해주세요")) + } } } } diff --git a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/artistsearch/ArtistSearchViewHolder.kt b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/artistsearch/ArtistSearchViewHolder.kt index 01318c966..a3c7e6ff5 100644 --- a/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/artistsearch/ArtistSearchViewHolder.kt +++ b/android/festago/presentation/src/main/java/com/festago/festago/presentation/ui/search/artistsearch/ArtistSearchViewHolder.kt @@ -19,14 +19,22 @@ class ArtistSearchViewHolder( fun bind(item: ArtistSearchItemUiState) { binding.item = item - binding.tvTodayStageCount.setStageCount( - count = item.todayStage, - stringRes = R.string.search_artist_tv_today_stage_count, - ) - binding.tvUpcomingStageCount.setStageCount( - item.upcomingStage, - stringRes = R.string.search_artist_tv_upcoming_stage_count, - ) + + if (item.todayStage == 0 && item.upcomingStage == 0) { + binding.tvTodayStageCount.visibility = TextView.GONE + binding.tvUpcomingStageCount.visibility = TextView.GONE + } else { + binding.tvTodayStageCount.setStageCount( + count = item.todayStage, + stringRes = R.string.search_artist_tv_today_stage_count, + ) + + binding.tvUpcomingStageCount.setStageCount( + item.upcomingStage, + stringRes = R.string.search_artist_tv_upcoming_stage_count, + ) + binding.tvEmptyStage.visibility = TextView.GONE + } } private fun TextView.setStageCount(count: Int, @StringRes stringRes: Int) { @@ -35,9 +43,15 @@ class ArtistSearchViewHolder( getPartialColorText( start = COLOR_INDEX, end = COLOR_INDEX + count.toString().length, - color = context.getColor(R.color.secondary_pink_01), + color = when (count) { + 0 -> context.getColor(R.color.contents_gray_05) + else -> context.getColor(R.color.secondary_pink_01) + }, ) } + if (count == 0) { + setTextColor(context.getColor(R.color.contents_gray_05)) + } } private fun SpannableString.getPartialColorText( diff --git a/android/festago/presentation/src/main/res/layout/fragment_bookmark_list.xml b/android/festago/presentation/src/main/res/layout/fragment_bookmark_list.xml index 6cecb3457..497ae5060 100644 --- a/android/festago/presentation/src/main/res/layout/fragment_bookmark_list.xml +++ b/android/festago/presentation/src/main/res/layout/fragment_bookmark_list.xml @@ -30,6 +30,7 @@ app:tabGravity="fill" app:tabIndicatorColor="@color/contents_gray_07" app:tabIndicatorFullWidth="false" + app:tabRippleColor="@color/contents_gray_04" app:tabIndicatorHeight="2dp" app:tabSelectedTextColor="@color/contents_gray_07" app:tabTextAppearance="@style/H4Bold16Lh20" diff --git a/android/festago/presentation/src/main/res/layout/item_search_artist.xml b/android/festago/presentation/src/main/res/layout/item_search_artist.xml index a2bfc0e66..09794ebc5 100644 --- a/android/festago/presentation/src/main/res/layout/item_search_artist.xml +++ b/android/festago/presentation/src/main/res/layout/item_search_artist.xml @@ -36,8 +36,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:importantForAccessibility="no" - android:scaleType="centerCrop" - tools:src="@drawable/ic_launcher_foreground" /> + android:scaleType="centerCrop"/> + + diff --git a/android/festago/presentation/src/main/res/values/strings.xml b/android/festago/presentation/src/main/res/values/strings.xml index 0f23954fb..93d54c339 100644 --- a/android/festago/presentation/src/main/res/values/strings.xml +++ b/android/festago/presentation/src/main/res/values/strings.xml @@ -28,8 +28,8 @@ D%1$s 아직 축제가 없어요 - 아티스트를 북마크 했습니다 - 북마크를 취소했습니다 + 북마크에 추가했어요 + 북마크에서 삭제했어요 알림 @@ -38,8 +38,8 @@ 아직 라인업이 공개되지 않았어요 - 축제를 북마크 했습니다 - 북마크를 취소했습니다 + 북마크에 추가했어요 + 북마크에서 삭제했어요 진행 중 @@ -51,8 +51,8 @@ 아직 축제가 없어요 - 학교를 북마크 했습니다 - 북마크를 취소했습니다 + 북마크에 추가했어요 + 북마크에서 삭제했어요 학교명, 아티스트명, 축제명으로 입력하세요. @@ -68,6 +68,7 @@ 예정 없음 오늘 공연 %d개 공연 예정 %d개 + 예정 없음 앗! 검색 결과가 없네요 찾으시는 정보가 없다면 저희에게 알려주세요 추가 요청하러 가기