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.huanchengfly.tieba.post.R
|
||||
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.models.database.Block
|
||||
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.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.LongClickMenu
|
||||
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.TitleCentredToolbar
|
||||
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.ramcosta.composedestinations.annotation.Destination
|
||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||
import kotlinx.coroutines.flow.filterIsInstance
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalPagerApi::class)
|
||||
|
|
@ -186,17 +186,13 @@ fun BlockSettingsPage(
|
|||
) { paddingValues ->
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
LaunchedEffect(null) {
|
||||
coroutineScope.launch {
|
||||
viewModel.uiEventFlow
|
||||
.filterIsInstance<BlockSettingsUiEvent.Success>()
|
||||
.collect {
|
||||
snackbarHostState.showSnackbar(
|
||||
when (it) {
|
||||
is BlockSettingsUiEvent.Success.Add -> context.getString(R.string.toast_add_success)
|
||||
is BlockSettingsUiEvent.Success.Delete -> context.getString(R.string.toast_delete_success)
|
||||
}
|
||||
)
|
||||
onEvent<BlockSettingsUiEvent.Success>(viewModel) {
|
||||
snackbarHostState.showSnackbar(
|
||||
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(
|
||||
|
|
@ -206,28 +202,36 @@ fun BlockSettingsPage(
|
|||
contentPadding = paddingValues,
|
||||
verticalAlignment = Alignment.Top
|
||||
) { position ->
|
||||
if (isLoading) {
|
||||
LazyColumn {
|
||||
items(4) {
|
||||
BlockItemPlaceholder()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val items = if (position == 0) blackList else whiteList
|
||||
if (items.isNotEmpty()) {
|
||||
LazyColumn {
|
||||
items(items, key = { it.id }) {
|
||||
LongClickMenu(menuContent = {
|
||||
DropdownMenuItem(onClick = { viewModel.send(BlockSettingsUiIntent.Delete(it.id)) }) {
|
||||
Text(text = stringResource(id = R.string.title_delete))
|
||||
}
|
||||
}) {
|
||||
BlockItem(item = it)
|
||||
}
|
||||
val items = if (position == 0) blackList else whiteList
|
||||
StateScreen(
|
||||
isEmpty = items.isEmpty(),
|
||||
isError = false,
|
||||
isLoading = isLoading,
|
||||
onReload = { viewModel.send(BlockSettingsUiIntent.Load) },
|
||||
loadingScreen = {
|
||||
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
||||
items(4) {
|
||||
BlockItemPlaceholder()
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
LazyColumn {
|
||||
items(items, key = { it.id }) {
|
||||
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_history_failure">删除历史记录失败 %s</string>
|
||||
<string name="delete_history_success">删除历史记录成功</string>
|
||||
<string name="error_tip">出错了</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Reference in New Issue