lce
lce copied to clipboard
Add support for folding into composables
Whould it make sence for this library to be able to fold types to composables? Maybe an extension that supports composable?
I have done something like this to convert the types into something that can be representable to the user:
@Composable
inline fun <C> UCT<C>.Compose(
crossinline onLoading: @Composable () -> Unit,
crossinline onError: @Composable (Throwable) -> Unit,
crossinline onContent: @Composable (C) -> Unit
) {
return ComposeTypes(
onLoading = { onLoading() },
onContent = { onContent(it.value) },
onError = { onError(it.value) }
)
}
@Composable
inline fun <C> UCT<C>.ComposeTypes(
crossinline onLoading: @Composable (Type.Loading.UnitType) -> Unit,
crossinline onContent: @Composable (Type.Content<C>) -> Unit,
crossinline onError: @Composable (Type.Error.ThrowableType) -> Unit
) {
return when (val type = asLceType()) {
is Type.Loading.UnitType -> onLoading(type)
is Type.Content -> onContent(type)
is Type.Error.ThrowableType -> onError(type)
else -> throw IllegalStateException("this should not happen: $type")
}
}
and then the usages could be something like this:
val uiState by remember {
mutableStateOf(UCT.content("hello earth!"))
}
uiState.Compose(
onError = {
Text(text = it.message ?: "")
ErrorView(stringResource(id = R.string.error))
},
onLoading = {
LoadingView(stringResource(id = R.string.loading))
},
onContent = {
Text(text = it)
}
)
Hey, thanks for submitting an issue. This makes sense to me, I think we should have lce-compose module for such utilities.
Looking at what I see in our codebase, there seems to be some nuance around animations. We aren't using fold because of the way animation container also needs to know when to animate out which depends on nullability of the model. I wonder if there is a public API that would be simple yet flexible or maybe we need to have two options.
@Composable
inline fun <Content> UCT<Content>.Render(
crossinline onLoading: @Composable () -> Unit,
crossinline onError: @Composable (Throwable) -> Unit,
crossinline onContent: @Composable (C) -> Unit
) {
AnimateContentIn(loadingOrNull()) { onLoading() }
AnimateContentIn(errorOrNull()) { onError(it) }
AnimateContentIn(contentOrNull()) { onContent(it) }
}
@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun <T> AnimateContentIn(model: T?, content: @Composable (T) -> Unit) {
AnimatedVisibility(visible = model != null, enter = fadeIn(), exit = fadeOut()) {
model?.let { content(it) }
}
}
Any movement on this?