feat: 状态屏
This commit is contained in:
parent
d07feb9ecb
commit
77dbab6483
|
|
@ -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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue