Skip to content

Commit

Permalink
[Feat] 검색 결과 화면 UI 작업
Browse files Browse the repository at this point in the history
  • Loading branch information
JaesungLeee committed Oct 1, 2024
1 parent 83da642 commit e395e81
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ internal fun SearchDetailScreen(
uiState.isLoading -> {
SearchDetailLoadingContent(
modifier = Modifier.fillMaxSize(),
uiState = uiState
isLoading = uiState.isLoading
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import team.ppac.common.android.util.showSkeleton
import team.ppac.designsystem.foundation.FarmemeRadius
import team.ppac.search.detail.mvi.SearchDetailUiState

@Composable
internal fun SearchDetailLoadingContent(
modifier: Modifier = Modifier,
uiState: SearchDetailUiState,
isLoading: Boolean,
) {
Column(
modifier = modifier
Expand All @@ -38,7 +37,7 @@ internal fun SearchDetailLoadingContent(
.height(18.dp)
.padding(start = 20.dp)
.clip(FarmemeRadius.Radius4.shape)
.showSkeleton(isLoading = uiState.isLoading)
.showSkeleton(isLoading = isLoading)
)
Spacer(modifier = Modifier.size(20.dp))
Row(
Expand All @@ -56,23 +55,23 @@ internal fun SearchDetailLoadingContent(
.fillMaxWidth()
.height(210.dp)
.clip(RoundedCornerShape(16.dp))
.showSkeleton(isLoading = uiState.isLoading)
.showSkeleton(isLoading = isLoading)
)
Spacer(modifier = Modifier.size(10.dp))
Box(
modifier = Modifier
.fillMaxWidth()
.height(18.dp)
.clip(FarmemeRadius.Radius4.shape)
.showSkeleton(isLoading = uiState.isLoading)
.showSkeleton(isLoading = isLoading)
)
Spacer(modifier = Modifier.size(10.dp))
Box(
modifier = Modifier
.width(80.dp)
.height(18.dp)
.clip(FarmemeRadius.Radius4.shape)
.showSkeleton(isLoading = uiState.isLoading)
.showSkeleton(isLoading = isLoading)
)
}
}
Expand All @@ -86,7 +85,7 @@ private fun SearchDetailLoadingContentPreview() {
Box(modifier = Modifier.background(Color.White)) {
SearchDetailLoadingContent(
modifier = Modifier.fillMaxSize(),
uiState = SearchDetailUiState.INITIAL_STATE
isLoading = true
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ internal fun SearchResultRoute(
SearchResultScreen(
modifier = modifier,
uiState = uiState,
onQueryChange = viewModel::updateSearchQuery
onQueryChange = viewModel::updateSearchQuery,
handleLoadStates = viewModel::handleLoadErrorStates,
onRetryClick = {},
onMemeClick = {},
onCopyClick = { _, _ ->},
)
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,91 @@
package team.ppac.search.result

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.LayoutDirection
import androidx.paging.LoadStates
import team.ppac.common.android.component.error.FarmemeErrorScreen
import team.ppac.common.android.extension.collectPagingItemsWithHandleState
import team.ppac.designsystem.component.scaffold.FarmemeScaffold
import team.ppac.designsystem.component.tabbar.TabBarHeight
import team.ppac.designsystem.component.toolbar.FarmemeSearchToolbar
import team.ppac.search.detail.component.EmptyResultContent
import team.ppac.search.detail.component.SearchDetailLoadingContent
import team.ppac.search.detail.component.SearchDetailResultContent
import team.ppac.search.result.mvi.SearchResultUiState

@Composable
internal fun SearchResultScreen(
modifier: Modifier = Modifier,
uiState: SearchResultUiState,
handleLoadStates: (LoadStates) -> Unit,
onQueryChange: (String) -> Unit,
onRetryClick: () -> Unit,
onMemeClick: (String) -> Unit,
onCopyClick: (String, String) -> Unit,
) {
FarmemeScaffold(
modifier = modifier.fillMaxSize(),
topBar = {
FarmemeSearchToolbar(
text = uiState.query,
onTextChanged = onQueryChange
val searchResults = uiState.searchResults.collectPagingItemsWithHandleState(handleLoadStates)

when {
uiState.isError -> {
FarmemeErrorScreen(
modifier = Modifier
.fillMaxSize()
.padding(bottom = TabBarHeight),
title = "정보를 불러오지 못 했어요.\n새로고침 해주세요.",
onRetryClick = onRetryClick
)
}
) {

else -> {
FarmemeScaffold(
modifier = modifier.fillMaxSize(),
topBar = {
FarmemeSearchToolbar(
text = uiState.query,
onTextChanged = onQueryChange
)
}
) { paddingValues ->
val innerPadding = PaddingValues(
top = paddingValues.calculateTopPadding(),
start = paddingValues.calculateStartPadding(LayoutDirection.Ltr),
end = paddingValues.calculateEndPadding(LayoutDirection.Ltr),
bottom = paddingValues.calculateBottomPadding() + TabBarHeight
)

when {
uiState.isLoading -> {
SearchDetailLoadingContent(
modifier = Modifier.fillMaxSize(),
isLoading = uiState.isLoading
)
}

else -> {
Column(
modifier = Modifier.padding(innerPadding)
) {
if (uiState.totalMemeCount == 0) {
EmptyResultContent()
} else {
SearchDetailResultContent(
totalItemCount = uiState.totalMemeCount,
searchResults = searchResults,
onMemeClick = onMemeClick,
onCopyClick = onCopyClick,
)
}
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package team.ppac.search.result

import androidx.lifecycle.SavedStateHandle
import androidx.paging.LoadState
import androidx.paging.LoadStates
import dagger.hilt.android.lifecycle.HiltViewModel
import team.ppac.common.android.base.BaseViewModel
import team.ppac.errorhandling.FarmemeNetworkException
import team.ppac.search.result.mvi.SearchResultIntent
import team.ppac.search.result.mvi.SearchResultSideEffect
import team.ppac.search.result.mvi.SearchResultUiState
Expand All @@ -28,4 +31,25 @@ class SearchResultViewModel @Inject constructor(
fun updateSearchQuery(query: String) {
reduce { copy(query = query) }
}

fun handleLoadErrorStates(loadStates: LoadStates) {
val errorLoadState = arrayOf(
loadStates.prepend,
loadStates.append,
loadStates.refresh
).filterIsInstance(LoadState.Error::class.java).firstOrNull()

val exception = errorLoadState?.error
if (exception != null) {
when (exception) {
is FarmemeNetworkException -> {
updateErrorState(isError = true)
}
}
}
}

private fun updateErrorState(isError: Boolean) {
reduce { copy(isError = isError) }
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
package team.ppac.search.result.mvi

import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import team.ppac.common.android.base.UiState
import team.ppac.search.detail.model.SearchResultUiModel

data class SearchResultUiState(
val isLoading: Boolean,
val query: String
val isError: Boolean,
val query: String,
val totalMemeCount: Int,
val searchResults: Flow<PagingData<SearchResultUiModel>>,
) : UiState {

companion object {
val INITIAL_STATE = SearchResultUiState(
isLoading = true,
query = ""
isError = false,
query = "",
totalMemeCount = 0,
searchResults = flowOf(PagingData.empty()),
)
}
}

0 comments on commit e395e81

Please sign in to comment.