feat: 动态页面状态屏

This commit is contained in:
HuanCheng65 2023-10-05 02:06:52 +08:00
parent 71a11f3496
commit a24d22e3f3
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
2 changed files with 112 additions and 72 deletions

View File

@ -33,6 +33,7 @@ import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@ -62,11 +63,13 @@ import com.huanchengfly.tieba.post.ui.page.destinations.ThreadPageDestination
import com.huanchengfly.tieba.post.ui.widgets.compose.BlockTip import com.huanchengfly.tieba.post.ui.widgets.compose.BlockTip
import com.huanchengfly.tieba.post.ui.widgets.compose.BlockableContent import com.huanchengfly.tieba.post.ui.widgets.compose.BlockableContent
import com.huanchengfly.tieba.post.ui.widgets.compose.Container import com.huanchengfly.tieba.post.ui.widgets.compose.Container
import com.huanchengfly.tieba.post.ui.widgets.compose.ErrorScreen
import com.huanchengfly.tieba.post.ui.widgets.compose.FeedCard import com.huanchengfly.tieba.post.ui.widgets.compose.FeedCard
import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad
import com.huanchengfly.tieba.post.ui.widgets.compose.LoadMoreLayout import com.huanchengfly.tieba.post.ui.widgets.compose.LoadMoreLayout
import com.huanchengfly.tieba.post.ui.widgets.compose.MyLazyColumn import com.huanchengfly.tieba.post.ui.widgets.compose.MyLazyColumn
import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalDivider import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalDivider
import com.huanchengfly.tieba.post.ui.widgets.compose.states.StateScreen
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -98,6 +101,10 @@ fun PersonalizedPage(
prop1 = PersonalizedUiState::data, prop1 = PersonalizedUiState::data,
initial = persistentListOf() initial = persistentListOf()
) )
val error by viewModel.uiState.collectPartialAsState(
prop1 = PersonalizedUiState::error,
initial = null
)
val refreshPosition by viewModel.uiState.collectPartialAsState( val refreshPosition by viewModel.uiState.collectPartialAsState(
prop1 = PersonalizedUiState::refreshPosition, prop1 = PersonalizedUiState::refreshPosition,
initial = 0 initial = 0
@ -112,6 +119,16 @@ fun PersonalizedPage(
) )
val lazyListState = rememberLazyListState() val lazyListState = rememberLazyListState()
viewModel.bindScrollToTopEvent(lazyListState = lazyListState) viewModel.bindScrollToTopEvent(lazyListState = lazyListState)
val isEmpty by remember {
derivedStateOf {
data.isEmpty()
}
}
val isError by remember {
derivedStateOf {
error != null
}
}
var refreshCount by remember { var refreshCount by remember {
mutableIntStateOf(0) mutableIntStateOf(0)
} }
@ -147,6 +164,19 @@ fun PersonalizedPage(
// } // }
// } // }
// } // }
StateScreen(
isEmpty = isEmpty,
isError = isError,
isLoading = isRefreshing,
onReload = { viewModel.send(PersonalizedUiIntent.Refresh) },
errorScreen = {
error?.let {
ErrorScreen(
error = it.get()
)
}
}
) {
Box(modifier = Modifier.pullRefresh(pullRefreshState)) { Box(modifier = Modifier.pullRefresh(pullRefreshState)) {
LoadMoreLayout( LoadMoreLayout(
isLoading = isLoadingMore, isLoading = isLoadingMore,
@ -220,6 +250,7 @@ fun PersonalizedPage(
RefreshTip(refreshCount = refreshCount) RefreshTip(refreshCount = refreshCount)
} }
} }
}
} }
@Composable @Composable

View File

@ -145,7 +145,7 @@ class PersonalizedViewModel @Inject constructor() :
} }
sealed interface PersonalizedUiIntent : UiIntent { sealed interface PersonalizedUiIntent : UiIntent {
object Refresh : PersonalizedUiIntent data object Refresh : PersonalizedUiIntent
data class LoadMore(val page: Int) : PersonalizedUiIntent data class LoadMore(val page: Int) : PersonalizedUiIntent
@ -282,10 +282,14 @@ sealed interface PersonalizedPartialChange : PartialChange<PersonalizedUiState>
data = (data + oldState.data).toImmutableList(), data = (data + oldState.data).toImmutableList(),
refreshPosition = if (oldState.data.isEmpty()) 0 else data.size refreshPosition = if (oldState.data.isEmpty()) 0 else data.size
) )
is Failure -> oldState.copy(isRefreshing = false)
is Failure -> oldState.copy(
isRefreshing = false,
error = error.wrapImmutable()
)
} }
object Start: Refresh() data object Start : Refresh()
data class Success( data class Success(
val data: List<ThreadItemData>, val data: List<ThreadItemData>,
@ -305,10 +309,14 @@ sealed interface PersonalizedPartialChange : PartialChange<PersonalizedUiState>
currentPage = currentPage, currentPage = currentPage,
data = (oldState.data + data).toImmutableList(), data = (oldState.data + data).toImmutableList(),
) )
is Failure -> oldState.copy(isLoadingMore = false)
is Failure -> oldState.copy(
isLoadingMore = false,
error = error.wrapImmutable()
)
} }
object Start: LoadMore() data object Start : LoadMore()
data class Success( data class Success(
val currentPage: Int, val currentPage: Int,
@ -325,6 +333,7 @@ sealed interface PersonalizedPartialChange : PartialChange<PersonalizedUiState>
data class PersonalizedUiState( data class PersonalizedUiState(
val isRefreshing: Boolean = true, val isRefreshing: Boolean = true,
val isLoadingMore: Boolean = false, val isLoadingMore: Boolean = false,
val error: ImmutableHolder<Throwable>? = null,
val currentPage: Int = 1, val currentPage: Int = 1,
val data: ImmutableList<ThreadItemData> = persistentListOf(), val data: ImmutableList<ThreadItemData> = persistentListOf(),
val hiddenThreadIds: ImmutableList<Long> = persistentListOf(), val hiddenThreadIds: ImmutableList<Long> = persistentListOf(),