Merge pull request #7181 from thundernest/add_content_loading_error_view
Add content loading error view
This commit is contained in:
commit
8d8450bcfe
6 changed files with 277 additions and 68 deletions
|
@ -0,0 +1,31 @@
|
|||
package app.k9mail.ui.catalog.ui.common.list
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.grid.GridItemSpan
|
||||
import androidx.compose.foundation.lazy.grid.LazyGridScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextCaption
|
||||
import app.k9mail.core.ui.compose.theme.MainTheme
|
||||
|
||||
fun LazyGridScope.sectionInfoItem(
|
||||
text: String,
|
||||
) {
|
||||
item(span = { GridItemSpan(maxLineSpan) }) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
start = MainTheme.spacings.double,
|
||||
end = MainTheme.spacings.double,
|
||||
),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
TextCaption(
|
||||
text = text,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,23 @@
|
|||
package app.k9mail.ui.catalog.ui.molecule.items
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.lazy.grid.LazyGridScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextSubtitle1
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorState
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorView
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.ErrorView
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.LoadingView
|
||||
import app.k9mail.ui.catalog.ui.common.list.ItemOutlined
|
||||
import app.k9mail.ui.catalog.ui.common.list.sectionHeaderItem
|
||||
import app.k9mail.ui.catalog.ui.common.list.sectionInfoItem
|
||||
import app.k9mail.ui.catalog.ui.common.list.sectionSubtitleItem
|
||||
|
||||
fun LazyGridScope.stateItems() {
|
||||
|
@ -33,4 +46,52 @@ fun LazyGridScope.stateItems() {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
sectionHeaderItem(text = "ContentLoadingErrorView")
|
||||
sectionInfoItem(text = "Click below to change state")
|
||||
item {
|
||||
Column {
|
||||
ItemOutlined {
|
||||
StatefulContentLoadingErrorState()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun StatefulContentLoadingErrorState() {
|
||||
val state = remember {
|
||||
mutableStateOf(ContentLoadingErrorState.Loading)
|
||||
}
|
||||
|
||||
ContentLoadingErrorView(
|
||||
state = state.value,
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
when (state.value) {
|
||||
ContentLoadingErrorState.Loading -> {
|
||||
state.value = ContentLoadingErrorState.Content
|
||||
}
|
||||
|
||||
ContentLoadingErrorState.Content -> {
|
||||
state.value = ContentLoadingErrorState.Error
|
||||
}
|
||||
|
||||
ContentLoadingErrorState.Error -> {
|
||||
state.value = ContentLoadingErrorState.Loading
|
||||
}
|
||||
}
|
||||
}
|
||||
.height(200.dp)
|
||||
.fillMaxSize(),
|
||||
error = {
|
||||
TextSubtitle1(text = "Error")
|
||||
},
|
||||
loading = {
|
||||
TextSubtitle1(text = "Loading...")
|
||||
},
|
||||
content = {
|
||||
TextSubtitle1(text = "Content")
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextSubtitle1
|
||||
import app.k9mail.core.ui.compose.theme.PreviewWithThemes
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
fun ContentLoadingErrorView(
|
||||
state: ContentLoadingErrorState,
|
||||
loading: @Composable () -> Unit,
|
||||
error: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
contentAlignment: Alignment = Alignment.Center,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier,
|
||||
contentAlignment = contentAlignment,
|
||||
) {
|
||||
AnimatedContent(
|
||||
targetState = state,
|
||||
label = "ContentLoadingErrorView",
|
||||
) { targetState ->
|
||||
when (targetState) {
|
||||
ContentLoadingErrorState.Loading -> loading()
|
||||
ContentLoadingErrorState.Content -> content()
|
||||
ContentLoadingErrorState.Error -> error()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class ContentLoadingErrorState {
|
||||
Loading, Content, Error
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ContentLoadingErrorViewPreview() {
|
||||
PreviewWithThemes {
|
||||
val state = remember {
|
||||
mutableStateOf(ContentLoadingErrorState.Loading)
|
||||
}
|
||||
|
||||
ContentLoadingErrorView(
|
||||
state = state.value,
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
when (state.value) {
|
||||
ContentLoadingErrorState.Loading -> {
|
||||
state.value = ContentLoadingErrorState.Content
|
||||
}
|
||||
|
||||
ContentLoadingErrorState.Content -> {
|
||||
state.value = ContentLoadingErrorState.Error
|
||||
}
|
||||
|
||||
ContentLoadingErrorState.Error -> {
|
||||
state.value = ContentLoadingErrorState.Loading
|
||||
}
|
||||
}
|
||||
}
|
||||
.fillMaxSize(),
|
||||
error = {
|
||||
TextSubtitle1(text = "Error")
|
||||
},
|
||||
loading = {
|
||||
TextSubtitle1(text = "Loading...")
|
||||
},
|
||||
content = {
|
||||
TextSubtitle1(text = "Content")
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
@ -26,15 +27,21 @@ fun ErrorView(
|
|||
modifier: Modifier = Modifier,
|
||||
message: String? = null,
|
||||
onRetry: () -> Unit = { },
|
||||
contentAlignment: Alignment = Alignment.Center,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.then(modifier),
|
||||
contentAlignment = contentAlignment,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
vertical = MainTheme.spacings.default,
|
||||
horizontal = MainTheme.spacings.double,
|
||||
)
|
||||
.then(modifier),
|
||||
),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
) {
|
||||
|
@ -71,6 +78,7 @@ fun ErrorView(
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package app.k9mail.core.ui.compose.designsystem.molecule
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
@ -18,13 +20,21 @@ import app.k9mail.core.ui.compose.theme.PreviewWithThemes
|
|||
fun LoadingView(
|
||||
modifier: Modifier = Modifier,
|
||||
message: String? = null,
|
||||
contentAlignment: Alignment = Alignment.Center,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.then(modifier),
|
||||
contentAlignment = contentAlignment,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(MainTheme.spacings.default)
|
||||
.then(modifier),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
if (message != null) {
|
||||
TextSubtitle1(text = message)
|
||||
|
@ -36,6 +46,7 @@ fun LoadingView(
|
|||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
|
|
|
@ -8,18 +8,21 @@ import androidx.compose.foundation.layout.imePadding
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.k9mail.core.ui.compose.common.DevicePreviews
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorState
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.ContentLoadingErrorView
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.ErrorView
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.LoadingView
|
||||
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
|
||||
import app.k9mail.core.ui.compose.theme.K9Theme
|
||||
import app.k9mail.core.ui.compose.theme.MainTheme
|
||||
import app.k9mail.core.ui.compose.theme.ThunderbirdTheme
|
||||
import app.k9mail.feature.account.common.ui.item.ErrorItem
|
||||
import app.k9mail.feature.account.common.ui.item.LoadingItem
|
||||
import app.k9mail.feature.account.oauth.ui.AccountOAuthContract
|
||||
import app.k9mail.feature.account.oauth.ui.preview.PreviewAccountOAuthViewModel
|
||||
import app.k9mail.feature.account.setup.R
|
||||
|
@ -43,28 +46,37 @@ internal fun AccountAutoDiscoveryContent(
|
|||
.then(modifier),
|
||||
) {
|
||||
val resources = LocalContext.current.resources
|
||||
val viewState = remember(key1 = state.isLoading, key2 = state.error) {
|
||||
when {
|
||||
state.isLoading -> ContentLoadingErrorState.Loading
|
||||
state.error != null -> ContentLoadingErrorState.Error
|
||||
else -> ContentLoadingErrorState.Content
|
||||
}
|
||||
}
|
||||
|
||||
ContentLoadingErrorView(
|
||||
state = viewState,
|
||||
loading = {
|
||||
LoadingView(
|
||||
message = stringResource(id = R.string.account_setup_auto_discovery_loading_message),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
},
|
||||
error = {
|
||||
ErrorView(
|
||||
title = stringResource(id = R.string.account_setup_auto_discovery_loading_error),
|
||||
message = state.error?.toResourceString(resources),
|
||||
onRetry = { onEvent(Event.OnRetryClicked) },
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
},
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.imePadding(),
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.double, Alignment.CenterVertically),
|
||||
) {
|
||||
if (state.isLoading) {
|
||||
item(key = "loading") {
|
||||
LoadingItem(
|
||||
message = stringResource(id = R.string.account_setup_auto_discovery_loading_message),
|
||||
)
|
||||
}
|
||||
} else if (state.error != null) {
|
||||
item(key = "error") {
|
||||
ErrorItem(
|
||||
title = stringResource(id = R.string.account_setup_auto_discovery_loading_error),
|
||||
message = state.error.toResourceString(resources),
|
||||
onRetry = { onEvent(Event.OnRetryClicked) },
|
||||
)
|
||||
}
|
||||
} else {
|
||||
contentItems(
|
||||
state = state,
|
||||
onEvent = onEvent,
|
||||
|
|
Loading…
Reference in a new issue