Skip to content

Commit

Permalink
De-duplicate loading logic in TreehouseAppContent#preload and `Tree…
Browse files Browse the repository at this point in the history
…houseAppContent#bind` (#1714)
  • Loading branch information
veyndan authored Nov 30, 2023
1 parent b0e57a4 commit d12783c
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import app.cash.redwood.ui.OnBackPressedDispatcher
import app.cash.redwood.ui.UiConfiguration
import kotlin.native.ObjCName
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.flow.StateFlow

/**
* A UI built as an interactive widget tree, that may or may not be actively running, or bound to an
Expand All @@ -43,7 +44,7 @@ public interface Content {
*/
public fun preload(
onBackPressedDispatcher: OnBackPressedDispatcher,
uiConfiguration: UiConfiguration,
uiConfiguration: StateFlow<UiConfiguration>,
)

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ private sealed interface ViewState {

data class Preloading(
val onBackPressedDispatcher: OnBackPressedDispatcher,
val uiConfiguration: UiConfiguration,
val uiConfiguration: StateFlow<UiConfiguration>,
) : ViewState

class Bound(
data class Bound(
val view: TreehouseView<*>,
) : ViewState
}
Expand Down Expand Up @@ -82,7 +82,7 @@ internal class TreehouseAppContent<A : AppService>(

override fun preload(
onBackPressedDispatcher: OnBackPressedDispatcher,
uiConfiguration: UiConfiguration,
uiConfiguration: StateFlow<UiConfiguration>,
) {
dispatchers.checkUi()
val previousState = stateFlow.value
Expand All @@ -101,7 +101,7 @@ internal class TreehouseAppContent<A : AppService>(
codeSession = codeSession,
isInitialLaunch = true,
onBackPressedDispatcher = onBackPressedDispatcher,
firstUiConfiguration = MutableStateFlow(nextViewState.uiConfiguration),
firstUiConfiguration = uiConfiguration,
),
)
}
Expand All @@ -116,34 +116,18 @@ internal class TreehouseAppContent<A : AppService>(

override fun bind(view: TreehouseView<*>) {
dispatchers.checkUi()

if (stateFlow.value.viewState == ViewState.Bound(view)) return // Idempotent.

preload(view.onBackPressedDispatcher, view.uiConfiguration)

val previousState = stateFlow.value
val previousViewState = previousState.viewState

if (previousViewState is ViewState.Bound && previousViewState.view == view) return // Idempotent.
check(previousViewState is ViewState.None || previousViewState is ViewState.Preloading)
check(previousViewState is ViewState.Preloading)

val nextViewState = ViewState.Bound(view)

// Start the code if necessary.
val codeSession = codeHost.codeSession
val nextCodeState = when {
previousState.codeState is CodeState.Idle && codeSession != null -> {
CodeState.Running(
startViewCodeContentBinding(
codeSession = codeSession,
isInitialLaunch = true,
onBackPressedDispatcher = nextViewState.view.onBackPressedDispatcher,
firstUiConfiguration = nextViewState.view.uiConfiguration,
),
)
}
else -> previousState.codeState
}

// Ask to get notified when code is ready.
if (previousViewState is ViewState.None) {
codeHost.addListener(this)
}
val nextCodeState = previousState.codeState

// Make sure we're showing something in the view; either loaded code or a spinner to show that
// code is coming.
Expand Down Expand Up @@ -201,7 +185,7 @@ internal class TreehouseAppContent<A : AppService>(
}

val uiConfiguration = when (viewState) {
is ViewState.Preloading -> MutableStateFlow(viewState.uiConfiguration)
is ViewState.Preloading -> viewState.uiConfiguration
is ViewState.Bound -> viewState.view.uiConfiguration
else -> error("unexpected receiveCodeSession with no view bound and no preload")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,6 @@ class CodeHostTest {
}

private fun treehouseView(name: String): FakeTreehouseView {
return FakeTreehouseView(onBackPressedDispatcher, name)
return FakeTreehouseView(name, onBackPressedDispatcher)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import app.cash.redwood.ui.UiConfiguration
import app.cash.redwood.widget.MutableListChildren
import app.cash.redwood.widget.SavedStateRegistry
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

internal class FakeTreehouseView(
override val onBackPressedDispatcher: FakeOnBackPressedDispatcher,
private val name: String,
override val onBackPressedDispatcher: FakeOnBackPressedDispatcher,
override val uiConfiguration: StateFlow<UiConfiguration> = MutableStateFlow(UiConfiguration()),
) : TreehouseView<FakeWidget> {
override val widgetSystem = FakeWidgetSystem()

Expand All @@ -41,8 +43,6 @@ internal class FakeTreehouseView(

override val children = MutableListChildren<FakeWidget>()

override val uiConfiguration = MutableStateFlow(UiConfiguration())

override val savedStateRegistry: SavedStateRegistry? = null

override fun reset() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import kotlin.test.Test
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
Expand All @@ -52,7 +53,7 @@ class TreehouseAppContentTest {
frameClockFactory = FakeFrameClock.Factory,
)
private val codeEventPublisher = FakeCodeEventPublisher(eventLog)
private val uiConfiguration = UiConfiguration()
private val uiConfiguration = MutableStateFlow(UiConfiguration())

@BeforeTest
fun setUp() {
Expand Down Expand Up @@ -487,6 +488,6 @@ class TreehouseAppContentTest {
}

private fun treehouseView(name: String): FakeTreehouseView {
return FakeTreehouseView(onBackPressedDispatcher, name)
return FakeTreehouseView(name, onBackPressedDispatcher, uiConfiguration)
}
}

0 comments on commit d12783c

Please sign in to comment.