123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- package eu.kanade.presentation.components
- import androidx.annotation.StringRes
- import androidx.compose.foundation.layout.Arrangement
- import androidx.compose.foundation.layout.Column
- import androidx.compose.foundation.layout.Row
- import androidx.compose.foundation.layout.Spacer
- import androidx.compose.foundation.layout.fillMaxSize
- import androidx.compose.foundation.layout.height
- import androidx.compose.foundation.layout.padding
- import androidx.compose.foundation.layout.paddingFromBaseline
- import androidx.compose.material.icons.Icons
- import androidx.compose.material.icons.outlined.HelpOutline
- import androidx.compose.material.icons.outlined.Refresh
- import androidx.compose.material3.Icon
- import androidx.compose.material3.MaterialTheme
- import androidx.compose.material3.Surface
- import androidx.compose.material3.Text
- import androidx.compose.material3.TextButton
- import androidx.compose.runtime.Composable
- import androidx.compose.runtime.remember
- import androidx.compose.ui.Alignment
- import androidx.compose.ui.Modifier
- import androidx.compose.ui.graphics.vector.ImageVector
- import androidx.compose.ui.res.stringResource
- import androidx.compose.ui.text.style.TextAlign
- import androidx.compose.ui.unit.dp
- import eu.kanade.presentation.theme.TachiyomiTheme
- import eu.kanade.presentation.util.ThemePreviews
- import eu.kanade.presentation.util.secondaryItemAlpha
- import eu.kanade.tachiyomi.R
- import tachiyomi.presentation.core.components.material.padding
- import kotlin.random.Random
- @Composable
- fun EmptyScreen(
- @StringRes textResource: Int,
- modifier: Modifier = Modifier,
- actions: List<EmptyScreenAction>? = null,
- ) {
- EmptyScreen(
- message = stringResource(textResource),
- modifier = modifier,
- actions = actions,
- )
- }
- @Composable
- fun EmptyScreen(
- message: String,
- modifier: Modifier = Modifier,
- actions: List<EmptyScreenAction>? = null,
- ) {
- val face = remember { getRandomErrorFace() }
- Column(
- modifier = modifier
- .fillMaxSize()
- .padding(horizontal = 24.dp),
- horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.Center,
- ) {
- Text(
- text = face,
- modifier = Modifier.secondaryItemAlpha(),
- style = MaterialTheme.typography.displayMedium,
- )
- Text(
- text = message,
- modifier = Modifier.paddingFromBaseline(top = 24.dp).secondaryItemAlpha(),
- style = MaterialTheme.typography.bodyMedium,
- textAlign = TextAlign.Center,
- )
- if (!actions.isNullOrEmpty()) {
- Row(
- modifier = Modifier
- .padding(
- top = 24.dp,
- start = 24.dp,
- end = 24.dp,
- ),
- horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
- ) {
- actions.forEach {
- ActionButton(
- modifier = Modifier.weight(1f),
- title = stringResource(it.stringResId),
- icon = it.icon,
- onClick = it.onClick,
- )
- }
- }
- }
- }
- }
- @Composable
- private fun ActionButton(
- modifier: Modifier = Modifier,
- title: String,
- icon: ImageVector,
- onClick: () -> Unit,
- ) {
- TextButton(
- modifier = modifier,
- onClick = onClick,
- ) {
- Column(horizontalAlignment = Alignment.CenterHorizontally) {
- Icon(
- imageVector = icon,
- contentDescription = null,
- )
- Spacer(Modifier.height(4.dp))
- Text(
- text = title,
- textAlign = TextAlign.Center,
- )
- }
- }
- }
- @ThemePreviews
- @Composable
- private fun NoActionPreview() {
- TachiyomiTheme {
- Surface {
- EmptyScreen(
- textResource = R.string.empty_screen,
- )
- }
- }
- }
- @ThemePreviews
- @Composable
- private fun WithActionPreview() {
- TachiyomiTheme {
- Surface {
- EmptyScreen(
- textResource = R.string.empty_screen,
- actions = listOf(
- EmptyScreenAction(
- stringResId = R.string.action_retry,
- icon = Icons.Outlined.Refresh,
- onClick = {},
- ),
- EmptyScreenAction(
- stringResId = R.string.getting_started_guide,
- icon = Icons.Outlined.HelpOutline,
- onClick = {},
- ),
- ),
- )
- }
- }
- }
- data class EmptyScreenAction(
- @StringRes val stringResId: Int,
- val icon: ImageVector,
- val onClick: () -> Unit,
- )
- private val ERROR_FACES = listOf(
- "(・o・;)",
- "Σ(ಠ_ಠ)",
- "ಥ_ಥ",
- "(˘・_・˘)",
- "(; ̄Д ̄)",
- "(・Д・。",
- )
- private fun getRandomErrorFace(): String {
- return ERROR_FACES[Random.nextInt(ERROR_FACES.size)]
- }
|