feat: 状态屏

This commit is contained in:
HuanCheng65 2023-01-24 15:51:33 +08:00
parent d07feb9ecb
commit 77dbab6483
No known key found for this signature in database
GPG Key ID: E9031EF91A805148
3 changed files with 103 additions and 32 deletions

View File

@ -47,12 +47,12 @@ import com.google.accompanist.placeholder.material.placeholder
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.arch.collectPartialAsState import com.huanchengfly.tieba.post.arch.collectPartialAsState
import com.huanchengfly.tieba.post.arch.onEvent
import com.huanchengfly.tieba.post.arch.pageViewModel import com.huanchengfly.tieba.post.arch.pageViewModel
import com.huanchengfly.tieba.post.models.database.Block import com.huanchengfly.tieba.post.models.database.Block
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
import com.huanchengfly.tieba.post.ui.page.main.BottomNavigationDivider import com.huanchengfly.tieba.post.ui.page.main.BottomNavigationDivider
import com.huanchengfly.tieba.post.ui.widgets.compose.BackNavigationIcon import com.huanchengfly.tieba.post.ui.widgets.compose.BackNavigationIcon
import com.huanchengfly.tieba.post.ui.widgets.compose.EmptyPlaceholder
import com.huanchengfly.tieba.post.ui.widgets.compose.LocalSnackbarHostState import com.huanchengfly.tieba.post.ui.widgets.compose.LocalSnackbarHostState
import com.huanchengfly.tieba.post.ui.widgets.compose.LongClickMenu import com.huanchengfly.tieba.post.ui.widgets.compose.LongClickMenu
import com.huanchengfly.tieba.post.ui.widgets.compose.MyScaffold import com.huanchengfly.tieba.post.ui.widgets.compose.MyScaffold
@ -60,10 +60,10 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.PagerTabIndicator
import com.huanchengfly.tieba.post.ui.widgets.compose.PromptDialog import com.huanchengfly.tieba.post.ui.widgets.compose.PromptDialog
import com.huanchengfly.tieba.post.ui.widgets.compose.TitleCentredToolbar import com.huanchengfly.tieba.post.ui.widgets.compose.TitleCentredToolbar
import com.huanchengfly.tieba.post.ui.widgets.compose.rememberDialogState import com.huanchengfly.tieba.post.ui.widgets.compose.rememberDialogState
import com.huanchengfly.tieba.post.ui.widgets.compose.states.StateScreen
import com.huanchengfly.tieba.post.utils.GsonUtil import com.huanchengfly.tieba.post.utils.GsonUtil
import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@OptIn(ExperimentalPagerApi::class) @OptIn(ExperimentalPagerApi::class)
@ -186,17 +186,13 @@ fun BlockSettingsPage(
) { paddingValues -> ) { paddingValues ->
val snackbarHostState = LocalSnackbarHostState.current val snackbarHostState = LocalSnackbarHostState.current
LaunchedEffect(null) { LaunchedEffect(null) {
coroutineScope.launch { onEvent<BlockSettingsUiEvent.Success>(viewModel) {
viewModel.uiEventFlow snackbarHostState.showSnackbar(
.filterIsInstance<BlockSettingsUiEvent.Success>() when (it) {
.collect { is BlockSettingsUiEvent.Success.Add -> context.getString(R.string.toast_add_success)
snackbarHostState.showSnackbar( is BlockSettingsUiEvent.Success.Delete -> context.getString(R.string.toast_delete_success)
when (it) {
is BlockSettingsUiEvent.Success.Add -> context.getString(R.string.toast_add_success)
is BlockSettingsUiEvent.Success.Delete -> context.getString(R.string.toast_delete_success)
}
)
} }
)
} }
} }
HorizontalPager( HorizontalPager(
@ -206,28 +202,36 @@ fun BlockSettingsPage(
contentPadding = paddingValues, contentPadding = paddingValues,
verticalAlignment = Alignment.Top verticalAlignment = Alignment.Top
) { position -> ) { position ->
if (isLoading) { val items = if (position == 0) blackList else whiteList
LazyColumn { StateScreen(
items(4) { isEmpty = items.isEmpty(),
BlockItemPlaceholder() isError = false,
} isLoading = isLoading,
} onReload = { viewModel.send(BlockSettingsUiIntent.Load) },
} else { loadingScreen = {
val items = if (position == 0) blackList else whiteList LazyColumn(modifier = Modifier.fillMaxSize()) {
if (items.isNotEmpty()) { items(4) {
LazyColumn { BlockItemPlaceholder()
items(items, key = { it.id }) { }
LongClickMenu(menuContent = { }
DropdownMenuItem(onClick = { viewModel.send(BlockSettingsUiIntent.Delete(it.id)) }) { }
Text(text = stringResource(id = R.string.title_delete)) ) {
} LazyColumn {
}) { items(items, key = { it.id }) {
BlockItem(item = it) LongClickMenu(menuContent = {
} DropdownMenuItem(onClick = {
viewModel.send(
BlockSettingsUiIntent.Delete(
it.id
)
)
}) {
Text(text = stringResource(id = R.string.title_delete))
}
}) {
BlockItem(item = it)
} }
} }
} else {
EmptyPlaceholder(modifier = Modifier.fillMaxSize())
} }
} }
} }

View File

@ -0,0 +1,66 @@
package com.huanchengfly.tieba.post.ui.widgets.compose.states
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
import com.huanchengfly.tieba.post.ui.widgets.compose.EmptyPlaceholder
val DefaultLoadingScreen: @Composable () -> Unit = {
CircularProgressIndicator(modifier = Modifier.size(48.dp), color = MaterialTheme.colors.primary)
}
val DefaultEmptyScreen: @Composable () -> Unit = {
EmptyPlaceholder()
}
val DefaultErrorScreen: @Composable () -> Unit = {
Text(
text = stringResource(id = R.string.error_tip),
style = MaterialTheme.typography.body1,
color = ExtendedTheme.colors.textSecondary
)
}
@Composable
fun StateScreen(
isEmpty: Boolean,
isError: Boolean,
isLoading: Boolean,
onReload: () -> Unit,
modifier: Modifier = Modifier,
emptyScreen: @Composable () -> Unit = DefaultEmptyScreen,
errorScreen: @Composable () -> Unit = DefaultErrorScreen,
loadingScreen: @Composable () -> Unit = DefaultLoadingScreen,
content: @Composable () -> Unit,
) {
Box(
modifier = Modifier
.fillMaxSize()
.then(modifier)
.clickable(enabled = isEmpty && !isLoading, onClick = onReload),
contentAlignment = Alignment.Center
) {
if (!isEmpty) {
content()
} else {
if (isLoading) {
loadingScreen()
} else if (isError) {
errorScreen()
} else {
emptyScreen()
}
}
}
}

View File

@ -628,4 +628,5 @@
<string name="delete_store_failure">取消收藏失败 %s</string> <string name="delete_store_failure">取消收藏失败 %s</string>
<string name="delete_history_failure">删除历史记录失败 %s</string> <string name="delete_history_failure">删除历史记录失败 %s</string>
<string name="delete_history_success">删除历史记录成功</string> <string name="delete_history_success">删除历史记录成功</string>
<string name="error_tip">出错了</string>
</resources> </resources>