Skip to content

Commit

Permalink
Merge pull request #235 from boostcampwm2023/feat/home_exception
Browse files Browse the repository at this point in the history
홈 페이지 예외처리
  • Loading branch information
junjange authored Dec 9, 2023
2 parents 93543d5 + 8a5fa51 commit e7b3eb3
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 91 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,22 @@ interface HomeContract :
val advertisements: Advertisements = Advertisements(null),
val videosTrend: VideosList = VideosList(null),
val videosTopRatedOldSchool: VideosList = VideosList(null),
val videosTopRatedChallenge: VideosList = VideosList(null)
val videosTopRatedChallenge: VideosList = VideosList(null),
val isErrorDialogShowing: Boolean = false,
val errorDialogTextResourceId: Int = 0
)

sealed interface Event {
data class OnClickedVideo(
val videosList: VideosList,
val page: Int
) : Event

data object OnErrorDialogDismissed : Event
}

sealed interface Effect {
data class OnClickedVideo(
data class NavigateToWatchingVideo(
val videosList: VideosList,
val page: Int
) : Effect
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.everyone.movemove_android.ui.screens.home

import android.content.Intent
import androidx.annotation.StringRes
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
Expand All @@ -11,6 +12,7 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
Expand Down Expand Up @@ -44,9 +46,10 @@ import com.everyone.domain.model.Videos
import com.everyone.domain.model.VideosList
import com.everyone.movemove_android.R
import com.everyone.movemove_android.base.use
import com.everyone.movemove_android.ui.ErrorDialog
import com.everyone.movemove_android.ui.LoadingDialog
import com.everyone.movemove_android.ui.StyledText
import com.everyone.movemove_android.ui.screens.home.HomeContract.Effect.OnClickedVideo
import com.everyone.movemove_android.ui.screens.home.HomeContract.Effect.NavigateToWatchingVideo
import com.everyone.movemove_android.ui.theme.Point
import com.everyone.movemove_android.ui.util.clickableWithoutRipple
import com.everyone.movemove_android.ui.watching_video.WatchingVideoActivity
Expand All @@ -68,7 +71,7 @@ fun HomeScreen(
LaunchedEffect(effect) {
effect.collectLatest { effect ->
when (effect) {
is OnClickedVideo -> navigateToActivity(
is NavigateToWatchingVideo -> navigateToActivity(
WatchingVideoActivity.newIntent(
context = context,
videosList = effect.videosList,
Expand All @@ -79,6 +82,13 @@ fun HomeScreen(
}
}

if (state.isErrorDialogShowing) {
ErrorDialog(
text = stringResource(id = state.errorDialogTextResourceId),
onDismissRequest = { event(HomeContract.Event.OnErrorDialogDismissed) }
)
}

if (state.isLoading) {
LoadingDialog()
} else {
Expand Down Expand Up @@ -182,17 +192,7 @@ fun MultiServiceAds(advertisements: Advertisements) {
)
}
} ?: run {
Box(
modifier = Modifier
.fillMaxWidth()
.height(220.dp)
) {
StyledText(
modifier = Modifier.align(Alignment.Center),
text = stringResource(R.string.empty_ads_title),
style = MaterialTheme.typography.titleMedium
)
}
EmptyVideoContent(stringResId = R.string.empty_ads_title)
}
}

Expand All @@ -209,6 +209,8 @@ fun MultiServiceAdsItem(
contentDescription = null,
contentScale = ContentScale.FillBounds,
)
} ?: run {
EmptyVideoContent(stringResId = R.string.empty_ads_title)
}
}

Expand Down Expand Up @@ -291,17 +293,7 @@ fun MoveMoveVideos(
}
}
} ?: run {
Box(
modifier = Modifier
.fillMaxWidth()
.height(250.dp),
) {
StyledText(
modifier = Modifier.align(Alignment.Center),
text = stringResource(R.string.empty_video_title),
style = MaterialTheme.typography.titleMedium,
)
}
EmptyVideoContent(stringResId = R.string.empty_video_title)
}
}

Expand All @@ -310,20 +302,37 @@ fun MoveMoveVideo(
modifier: Modifier,
videos: Videos,
) {
videos.video?.let { video ->
Card(
modifier = modifier
.width(150.dp)
.height(250.dp)
.padding(bottom = 8.dp),
shape = RoundedCornerShape(size = 8.dp),
) {
Card(
modifier = modifier
.width(150.dp)
.height(250.dp)
.padding(bottom = 8.dp),
shape = RoundedCornerShape(size = 8.dp),
) {
videos.video?.let { video ->
AsyncImage(
modifier = Modifier.fillMaxSize(),
model = video.thumbnailImageUrl,
contentDescription = null,
contentScale = ContentScale.Crop,
)
} ?: run {
EmptyVideoContent(stringResId = R.string.empty_video_title)
}
}
}

@Composable
fun EmptyVideoContent(@StringRes stringResId: Int) {
Box(
modifier = Modifier
.fillMaxSize()
.heightIn(min = 220.dp),
) {
StyledText(
modifier = Modifier.align(Alignment.Center),
text = stringResource(stringResId),
style = MaterialTheme.typography.titleSmall
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import com.everyone.domain.model.base.DataState
import com.everyone.domain.usecase.GetAdsUseCase
import com.everyone.domain.usecase.GetVideosTopRatedUseCase
import com.everyone.domain.usecase.GetVideosTrendUseCase
import com.everyone.movemove_android.R
import com.everyone.movemove_android.di.IoDispatcher
import com.everyone.movemove_android.di.MainImmediateDispatcher
import com.everyone.movemove_android.ui.screens.home.HomeContract.*
import com.everyone.movemove_android.ui.screens.home.HomeContract.Event.*
import com.everyone.movemove_android.ui.watching_video.WatchingVideoContract.Category
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
Expand All @@ -23,11 +26,13 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
import kotlinx.coroutines.withContext
import javax.inject.Inject

@HiltViewModel
class HomeViewModel @Inject constructor(
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
@MainImmediateDispatcher private val mainImmediateDispatcher: CoroutineDispatcher,
private val getAdsUseCase: GetAdsUseCase,
private val getVideosTrendUseCase: GetVideosTrendUseCase,
private val getVideosTopRatedUseCase: GetVideosTopRatedUseCase
Expand All @@ -39,7 +44,8 @@ class HomeViewModel @Inject constructor(
override val effect: SharedFlow<Effect> = _effect.asSharedFlow()

override fun event(event: Event) = when (event) {
is Event.OnClickedVideo -> onClickedVideo(event.videosList, event.page)
is OnClickedVideo -> onClickedVideo(event.videosList, event.page)
is OnErrorDialogDismissed -> onErrorDialogDismissed()
}

init {
Expand All @@ -51,89 +57,115 @@ class HomeViewModel @Inject constructor(

private fun onClickedVideo(videosList: VideosList, page: Int) {
viewModelScope.launch {
_effect.emit(Effect.OnClickedVideo(videosList, page))
_effect.emit(Effect.NavigateToWatchingVideo(videosList, page))
}
}

private fun getAds() {
loading(isLoading = true)
getAdsUseCase().onEach { result ->
when (result) {
is DataState.Success -> {
_state.update {
it.copy(
isLoading = false,
advertisements = result.data
)
viewModelScope.launch {
loading(isLoading = true)
getAdsUseCase().onEach { result ->
when (result) {
is DataState.Success -> {
_state.update {
it.copy(
isLoading = false,
advertisements = result.data
)
}
}
}

is DataState.Failure -> {
loading(isLoading = false)
is DataState.Failure -> {
loading(isLoading = false)
showErrorDialog(R.string.error_ads)
}
}
}
}.launchIn(viewModelScope + ioDispatcher)
}.launchIn(viewModelScope + ioDispatcher)
}
}

private fun getVideosTrend() {
loading(isLoading = true)
getVideosTrendUseCase(limit = LIMIT).onEach { result ->
when (result) {
is DataState.Success -> {
_state.update {
it.copy(
isLoading = false,
videosTrend = result.data
)
viewModelScope.launch {
loading(isLoading = true)
getVideosTrendUseCase(limit = LIMIT).onEach { result ->
when (result) {
is DataState.Success -> {
_state.update {
it.copy(
isLoading = false,
videosTrend = result.data
)
}
}
}

is DataState.Failure -> {
loading(isLoading = false)
is DataState.Failure -> {
showErrorDialog(R.string.error_video)
loading(isLoading = false)
}
}
}
}.launchIn(viewModelScope + ioDispatcher)
}.launchIn(viewModelScope + ioDispatcher)
}
}


private fun geVideosTopRated(category: Category) {
loading(isLoading = true)
getVideosTopRatedUseCase(category = category.displayName).onEach { result ->
when (result) {
is DataState.Success -> {
when (category) {
Category.CHALLENGE -> {
_state.update {
it.copy(
isLoading = false,
videosTopRatedChallenge = result.data
)
viewModelScope.launch {
loading(isLoading = true)
getVideosTopRatedUseCase(category = category.displayName).onEach { result ->
when (result) {
is DataState.Success -> {
when (category) {
Category.CHALLENGE -> {
_state.update {
it.copy(
isLoading = false,
videosTopRatedChallenge = result.data
)
}
}
}

Category.OLD_SCHOOL -> {
_state.update {
it.copy(
isLoading = false,
videosTopRatedOldSchool = result.data
)
Category.OLD_SCHOOL -> {
_state.update {
it.copy(
isLoading = false,
videosTopRatedOldSchool = result.data
)
}
}
}

else -> {}
else -> {}
}
}
}

is DataState.Failure -> {
loading(isLoading = false)
is DataState.Failure -> {
showErrorDialog(R.string.error_video)
loading(isLoading = false)
}
}
}
}.launchIn(viewModelScope + ioDispatcher)
}.launchIn(viewModelScope + ioDispatcher)
}
}

private fun showErrorDialog(textResourceId: Int) {
_state.update {
it.copy(
isErrorDialogShowing = true,
errorDialogTextResourceId = textResourceId
)
}
}

private fun loading(isLoading: Boolean) {
private fun onErrorDialogDismissed() {
_state.update {
it.copy(isLoading = isLoading)
it.copy(isErrorDialogShowing = false)
}
}

private suspend fun loading(isLoading: Boolean) {
withContext(mainImmediateDispatcher) {
_state.update {
it.copy(isLoading = isLoading)
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions client/presentation/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@

<!-- home-->
<string name="empty_ads_title">광고가 없습니다</string>
<string name="error_ads">광고를 가져 올 수 없습니다</string>
<string name="empty_video_title">영상이 없습니다</string>
<string name="error_video">영상을 가져 올 수 없습니다</string>

<!-- rating_video-->
<string name="rating_video_title">내가 점수를 준 영상 모아보기</string>
Expand Down

0 comments on commit e7b3eb3

Please sign in to comment.