Skip to content

Commit 85ff181

Browse files
committed
Simpler, safer ViewEnvironment and ViewRegistry management.
`ViewEnvironment(Map<ViewEnvironmentKey<*>, Any>)` makes it easy to build a `ViewEnvironment` whose with values that don't match the type of the `ViewEnvironmentKey`s. We deprecate it with an eye toward making it non-public down the road. In its place we introduce `ViewEnvironment.EMPTY`, and guide people to use it and the type safe `plus` operators. We introduce a pattern of providing more `plus` operators with new environment value types. For `ViewRegistry`, in addition to the `plus` operator we provide a set of `merge` methods, which finish the long overdue job of making it simpler to mess with `ViewEnvironment` without stomping on `ViewRegistry` entries, and to override them. `EnvironmentScreen.withRegistry` and `.withEnvironment` use these. Fixes #395.
1 parent 6099c59 commit 85ff181

File tree

36 files changed

+387
-199
lines changed

36 files changed

+387
-199
lines changed

samples/compose-samples/src/main/java/com/squareup/sample/compose/hellocompose/App.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ import com.squareup.workflow1.ui.ViewRegistry
1616
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
1717
import com.squareup.workflow1.ui.compose.WorkflowRendering
1818
import com.squareup.workflow1.ui.compose.renderAsState
19+
import com.squareup.workflow1.ui.plus
1920

20-
private val viewRegistry = ViewRegistry(HelloBinding)
21-
22-
private val viewEnvironment = ViewEnvironment(mapOf(ViewRegistry to viewRegistry))
21+
private val viewEnvironment = ViewEnvironment.EMPTY + ViewRegistry(HelloBinding)
2322

2423
@Composable fun App() {
2524
MaterialTheme {

samples/compose-samples/src/main/java/com/squareup/sample/compose/hellocomposebinding/HelloBindingActivity.kt

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ import com.squareup.workflow1.ui.WorkflowLayout
1515
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
1616
import com.squareup.workflow1.ui.compose.composeViewFactory
1717
import com.squareup.workflow1.ui.compose.withCompositionRoot
18+
import com.squareup.workflow1.ui.plus
1819
import com.squareup.workflow1.ui.renderWorkflowIn
1920
import kotlinx.coroutines.flow.StateFlow
2021

21-
@OptIn(WorkflowUiExperimentalApi::class)
22-
private val viewRegistry = ViewRegistry(HelloBinding)
23-
2422
@OptIn(WorkflowUiExperimentalApi::class)
2523
private val viewEnvironment =
26-
ViewEnvironment(mapOf(ViewRegistry to viewRegistry)).withCompositionRoot { content ->
24+
(ViewEnvironment.EMPTY + ViewRegistry(HelloBinding)).withCompositionRoot { content ->
2725
MaterialTheme(content = content)
2826
}
2927

@@ -37,22 +35,22 @@ class HelloBindingActivity : AppCompatActivity() {
3735

3836
val model: HelloBindingModel by viewModels()
3937
setContentView(
40-
WorkflowLayout(this).apply {
41-
start(
42-
renderings = model.renderings,
43-
environment = viewEnvironment
44-
)
45-
}
38+
WorkflowLayout(this).apply {
39+
start(
40+
renderings = model.renderings,
41+
environment = viewEnvironment
42+
)
43+
}
4644
)
4745
}
4846

4947
class HelloBindingModel(savedState: SavedStateHandle) : ViewModel() {
5048
@OptIn(WorkflowUiExperimentalApi::class)
5149
val renderings: StateFlow<Any> by lazy {
5250
renderWorkflowIn(
53-
workflow = HelloWorkflow,
54-
scope = viewModelScope,
55-
savedStateHandle = savedState
51+
workflow = HelloWorkflow,
52+
scope = viewModelScope,
53+
savedStateHandle = savedState
5654
)
5755
}
5856
}

samples/compose-samples/src/main/java/com/squareup/sample/compose/hellocomposeworkflow/HelloComposeWorkflow.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ object HelloComposeWorkflow : ComposeWorkflow<String, Toggle>() {
4848
@Preview(showBackground = true)
4949
@Composable fun HelloComposeWorkflowPreview() {
5050
val rendering by HelloComposeWorkflow.renderAsState(props = "hello", onOutput = {})
51-
WorkflowRendering(rendering, ViewEnvironment())
51+
WorkflowRendering(rendering, ViewEnvironment.EMPTY)
5252
}

samples/compose-samples/src/main/java/com/squareup/sample/compose/inlinerendering/InlineRenderingWorkflow.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ object InlineRenderingWorkflow : StatefulWorkflow<Unit, Int, Nothing, AndroidVie
5555
@Preview
5656
@Composable fun InlineRenderingWorkflowPreview() {
5757
val rendering by InlineRenderingWorkflow.renderAsState(props = Unit, onOutput = {})
58-
WorkflowRendering(rendering, ViewEnvironment())
58+
WorkflowRendering(rendering, ViewEnvironment.EMPTY)
5959
}
6060

6161
@OptIn(ExperimentalAnimationApi::class)

samples/compose-samples/src/main/java/com/squareup/sample/compose/nestedrenderings/NestedRenderingsActivity.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import com.squareup.workflow1.ui.ViewRegistry
1515
import com.squareup.workflow1.ui.WorkflowLayout
1616
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
1717
import com.squareup.workflow1.ui.compose.withCompositionRoot
18+
import com.squareup.workflow1.ui.plus
1819
import com.squareup.workflow1.ui.renderWorkflowIn
1920
import kotlinx.coroutines.flow.StateFlow
2021

@@ -26,7 +27,7 @@ private val viewRegistry = ViewRegistry(
2627

2728
@OptIn(WorkflowUiExperimentalApi::class)
2829
private val viewEnvironment =
29-
ViewEnvironment(mapOf(ViewRegistry to viewRegistry)).withCompositionRoot { content ->
30+
(ViewEnvironment.EMPTY + viewRegistry).withCompositionRoot { content ->
3031
CompositionLocalProvider(LocalBackgroundColor provides Color.Green) {
3132
content()
3233
}

samples/compose-samples/src/main/java/com/squareup/sample/compose/textinput/App.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@file:OptIn(WorkflowUiExperimentalApi::class)
2+
@file:Suppress("FunctionName")
23

34
package com.squareup.sample.compose.textinput
45

@@ -11,10 +12,9 @@ import com.squareup.workflow1.ui.ViewRegistry
1112
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
1213
import com.squareup.workflow1.ui.compose.WorkflowRendering
1314
import com.squareup.workflow1.ui.compose.renderAsState
15+
import com.squareup.workflow1.ui.plus
1416

15-
private val viewRegistry = ViewRegistry(TextInputViewFactory)
16-
17-
private val viewEnvironment = ViewEnvironment(mapOf(ViewRegistry to viewRegistry))
17+
private val viewEnvironment = ViewEnvironment.EMPTY + ViewRegistry(TextInputViewFactory)
1818

1919
@Composable fun TextInputApp() {
2020
MaterialTheme {

samples/containers/android/src/main/java/com/squareup/sample/container/overviewdetail/OverviewDetailConfig.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package com.squareup.sample.container.overviewdetail
22

3-
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
3+
import com.squareup.workflow1.ui.ViewEnvironment
44
import com.squareup.workflow1.ui.ViewEnvironmentKey
5+
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
56

67
/**
78
* [com.squareup.workflow1.ui.ViewEnvironment] value that informs views
@@ -34,3 +35,7 @@ enum class OverviewDetailConfig {
3435
override val default = None
3536
}
3637
}
38+
39+
@WorkflowUiExperimentalApi
40+
operator fun ViewEnvironment.plus(config: OverviewDetailConfig): ViewEnvironment =
41+
this + (OverviewDetailConfig to config)

samples/containers/android/src/main/java/com/squareup/sample/container/overviewdetail/OverviewDetailContainer.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ class OverviewDetailContainer(view: View) : ScreenViewRunner<OverviewDetailScree
5656
// Since we have two sibling back stacks, we need to give them each different
5757
// SavedStateRegistry key prefixes.
5858
val overviewViewEnvironment = viewEnvironment
59-
.withBackStackStateKeyPrefix(OverviewBackStackKey) + (OverviewDetailConfig to Overview)
59+
.withBackStackStateKeyPrefix(OverviewBackStackKey) + Overview
6060
overviewStub!!.show(rendering.overviewRendering, overviewViewEnvironment)
6161
rendering.detailRendering
6262
?.let { detail ->
6363
detailStub!!.actual.visibility = VISIBLE
6464
detailStub.show(
6565
detail,
66-
viewEnvironment + (OverviewDetailConfig to Detail)
66+
viewEnvironment + Detail
6767
)
6868
}
6969
?: run {
@@ -81,7 +81,7 @@ class OverviewDetailContainer(view: View) : ScreenViewRunner<OverviewDetailScree
8181
?.let { rendering.overviewRendering + it }
8282
?: rendering.overviewRendering
8383

84-
stub.show(combined, viewEnvironment + (OverviewDetailConfig to Single))
84+
stub.show(combined, viewEnvironment + Single)
8585
}
8686

8787
companion object : ScreenViewFactory<OverviewDetailScreen> by ScreenViewRunner.bind(

workflow-ui/compose-tooling/src/androidTest/java/com/squareup/workflow1/ui/compose/tooling/PreviewViewFactoryTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ internal class PreviewViewFactoryTest {
7979
composeRule.onNodeWithText("two").assertIsNotDisplayed()
8080
}
8181

82-
@Test fun customViewEnvironment() {
82+
@Test fun customViewEnvironment.EMPTY {
8383
composeRule.setContent {
8484
ParentConsumesCustomKeyPreview()
8585
}

workflow-ui/compose-tooling/src/main/java/com/squareup/workflow1/ui/compose/tooling/PreviewViewEnvironment.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.squareup.workflow1.ui.ViewEnvironment
1111
import com.squareup.workflow1.ui.ViewFactory
1212
import com.squareup.workflow1.ui.ViewRegistry
1313
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
14+
import com.squareup.workflow1.ui.plus
1415
import kotlin.reflect.KClass
1516

1617
/**
@@ -30,7 +31,7 @@ import kotlin.reflect.KClass
3031
PreviewViewRegistry(mainFactory, placeholderViewFactory(placeholderModifier))
3132
}
3233
return remember(viewRegistry, viewEnvironmentUpdater) {
33-
ViewEnvironment(mapOf(ViewRegistry to viewRegistry)).let { environment ->
34+
(ViewEnvironment.EMPTY + viewRegistry).let { environment ->
3435
// Give the preview a chance to add its own elements to the ViewEnvironment.
3536
viewEnvironmentUpdater?.let { it(environment) } ?: environment
3637
}

0 commit comments

Comments
 (0)