Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace DerivedState with StateFlow #77

Merged
merged 1 commit into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

/**
* Wrap an ErrorBoundary around other [Catch] composable functions to catch errors and render a fallback UI.
Expand Down Expand Up @@ -71,7 +72,7 @@ fun ErrorBoundary(
state: ErrorBoundaryState = remember { ErrorBoundaryState() },
content: @Composable () -> Unit
) {
val currentError by remember(state) { derivedStateOf { state.error } }
val currentError by state.error.collectAsState()
val onErrorCallback by rememberUpdatedState(newValue = onError)
val onResetCallback by rememberUpdatedState(newValue = onReset)
Box(modifier) {
Expand Down Expand Up @@ -115,13 +116,11 @@ class ErrorBoundaryContext(
*/
@Stable
class ErrorBoundaryState : CatchThrowHost {
private val hostMap = mutableStateMapOf<Any, Throwable>()
private val hostMap = mutableMapOf<Any, Throwable>()

/**
* Returns the caught error.
*/
val error: Throwable?
get() = hostMap.values.firstOrNull()
// FIXME: This can be fixed by enabling K2 mode
private val _error = MutableStateFlow<Throwable?>(null)
val error: StateFlow<Throwable?> = _error

override val keys: Set<Any> get() = hostMap.keys

Expand All @@ -131,9 +130,15 @@ class ErrorBoundaryState : CatchThrowHost {

override fun set(key: Any, error: Throwable) {
hostMap[key] = error
onStateChanged()
}

override fun remove(key: Any) {
hostMap.remove(key)
onStateChanged()
}

private fun onStateChanged() {
_error.value = hostMap.values.firstOrNull()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds

Expand Down Expand Up @@ -55,9 +56,7 @@ fun Suspense(
contentThreshold: Duration = 3.seconds,
content: @Composable () -> Unit
) {
val isAwaited by remember(state) {
derivedStateOf { state.isAwaited() }
}
val isAwaited by state.isAwaited.collectAsState()
var isFirstTime by remember { mutableStateOf(true) }
Box(modifier = modifier) {
CompositionLocalProvider(LocalAwaitHost provides state) {
Expand All @@ -80,7 +79,11 @@ fun Suspense(
*/
@Stable
class SuspenseState : AwaitHost {
private val hostMap = mutableStateMapOf<Any, Boolean>()
private val hostMap = mutableMapOf<Any, Boolean>()

// FIXME: This can be fixed by enabling K2 mode
private val _isAwaited = MutableStateFlow(false)
val isAwaited: StateFlow<Boolean> = _isAwaited

override val keys: Set<Any> get() = hostMap.keys

Expand All @@ -90,16 +93,15 @@ class SuspenseState : AwaitHost {

override fun set(key: Any, isAwaited: Boolean) {
hostMap[key] = isAwaited
onStateChanged()
}

override fun remove(key: Any) {
hostMap.remove(key)
onStateChanged()
}

/**
* Returns `true` if any of the [Await] is awaited.
*/
fun isAwaited(): Boolean {
return hostMap.any { it.value }
private fun onStateChanged() {
_isAwaited.value = hostMap.any { it.value }
}
}