Skip to content

Overhaul of Compose support. #689

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

Merged
merged 1 commit into from
Mar 2, 2022
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
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ android.useAndroidX=true
systemProp.org.gradle.internal.publish.checksums.insecure=true

GROUP=com.squareup.workflow1
VERSION_NAME=1.7.0-uiUpdate01-SNAPSHOT
VERSION_NAME=1.7.0-uiUpdate02-SNAPSHOT

POM_DESCRIPTION=Square Workflow

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.squareup.sample.compose.hellocompose.HelloWorkflow.Rendering
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.compose.composeViewFactory
import com.squareup.workflow1.ui.compose.composeScreenViewFactory

@OptIn(WorkflowUiExperimentalApi::class)
val HelloBinding = composeViewFactory<Rendering> { rendering, _ ->
val HelloBinding = composeScreenViewFactory<Rendering> { rendering, _ ->
Text(
rendering.message,
modifier = Modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.squareup.workflow1.Snapshot
import com.squareup.workflow1.StatefulWorkflow
import com.squareup.workflow1.action
import com.squareup.workflow1.parse
import com.squareup.workflow1.ui.Screen
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi

object HelloWorkflow : StatefulWorkflow<Unit, State, Nothing, Rendering>() {
enum class State {
Expand All @@ -20,10 +22,11 @@ object HelloWorkflow : StatefulWorkflow<Unit, State, Nothing, Rendering>() {
}
}

@OptIn(WorkflowUiExperimentalApi::class)
data class Rendering(
val message: String,
val onClick: () -> Unit
)
) : Screen

private val helloAction = action {
state = state.theOtherState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.squareup.sample.compose.hellocomposebinding.HelloWorkflow.Rendering
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.compose.composeViewFactory
import com.squareup.workflow1.ui.compose.composeScreenViewFactory
import com.squareup.workflow1.ui.compose.tooling.Preview

@OptIn(WorkflowUiExperimentalApi::class)
val HelloBinding = composeViewFactory<Rendering> { rendering, _ ->
val HelloBinding = composeScreenViewFactory<Rendering> { rendering, _ ->
Text(
rendering.message,
modifier = Modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.squareup.workflow1.Snapshot
import com.squareup.workflow1.StatefulWorkflow
import com.squareup.workflow1.action
import com.squareup.workflow1.parse
import com.squareup.workflow1.ui.Screen
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi

object HelloWorkflow : StatefulWorkflow<Unit, State, Nothing, Rendering>() {
enum class State {
Expand All @@ -20,10 +22,11 @@ object HelloWorkflow : StatefulWorkflow<Unit, State, Nothing, Rendering>() {
}
}

@OptIn(WorkflowUiExperimentalApi::class)
data class Rendering(
val message: String,
val onClick: () -> Unit
)
) : Screen

private val helloAction = action {
state = state.theOtherState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import com.squareup.workflow1.StatefulWorkflow
import com.squareup.workflow1.Workflow
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.compose.ComposeRendering
import com.squareup.workflow1.ui.compose.ComposeScreen

/**
* A stateless [Workflow] that [renders][RenderingContent] itself as a [Composable] function.
* Effectively defines an inline [ComposeRendering].
* Effectively defines an inline [ComposeScreen].
*
* This workflow does not have access to a [RenderContext] since render contexts are only valid
* during render passes, and this workflow's [RenderingContent] method is invoked after the render
Expand All @@ -28,8 +28,8 @@ import com.squareup.workflow1.ui.compose.ComposeRendering
* comes up.
*/
@WorkflowUiExperimentalApi
public abstract class ComposeWorkflow<in PropsT, out OutputT : Any> :
Workflow<PropsT, OutputT, ComposeRendering> {
abstract class ComposeWorkflow<in PropsT, out OutputT : Any> :
Workflow<PropsT, OutputT, ComposeScreen> {

/**
* Renders [props] by emitting Compose UI. This function will be called to update the UI whenever
Expand All @@ -40,21 +40,21 @@ public abstract class ComposeWorkflow<in PropsT, out OutputT : Any> :
* workflow's parent.
* @param viewEnvironment The [ViewEnvironment] passed down through the `ViewBinding` pipeline.
*/
@Composable public abstract fun RenderingContent(
@Composable abstract fun RenderingContent(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why no public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops! Good catch, thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, because this is a sample, no explicit API mode -- public is redundant.

props: PropsT,
outputSink: Sink<OutputT>,
viewEnvironment: ViewEnvironment
)

override fun asStatefulWorkflow(): StatefulWorkflow<PropsT, *, OutputT, ComposeRendering> =
override fun asStatefulWorkflow(): StatefulWorkflow<PropsT, *, OutputT, ComposeScreen> =
ComposeWorkflowImpl(this)
}

/**
* Returns a [ComposeWorkflow] that renders itself using the given [render] function.
*/
@WorkflowUiExperimentalApi
public inline fun <PropsT, OutputT : Any> Workflow.Companion.composed(
inline fun <PropsT, OutputT : Any> Workflow.Companion.composed(
crossinline render: @Composable (
props: PropsT,
outputSink: Sink<OutputT>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ import com.squareup.workflow1.action
import com.squareup.workflow1.contraMap
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.compose.ComposeRendering
import com.squareup.workflow1.ui.compose.ComposeScreen

@WorkflowUiExperimentalApi
internal class ComposeWorkflowImpl<PropsT, OutputT : Any>(
private val workflow: ComposeWorkflow<PropsT, OutputT>
) : StatefulWorkflow<PropsT, State<PropsT, OutputT>, OutputT, ComposeRendering>() {
) : StatefulWorkflow<PropsT, State<PropsT, OutputT>, OutputT, ComposeScreen>() {

// This doesn't need to be a @Model, it only gets set once, before the composable ever runs.
class SinkHolder<OutputT>(var sink: Sink<OutputT>? = null)

data class State<PropsT, OutputT>(
val propsHolder: MutableState<PropsT>,
val sinkHolder: SinkHolder<OutputT>,
val rendering: ComposeRendering
val rendering: ComposeScreen
)

override fun initialState(
Expand All @@ -38,7 +38,7 @@ internal class ComposeWorkflowImpl<PropsT, OutputT : Any>(
return State(
propsHolder,
sinkHolder,
object : ComposeRendering {
object : ComposeScreen {
@Composable override fun Content(viewEnvironment: ViewEnvironment) {
// The sink will get set on the first render pass, which must happen before this is first
// composed, so it should never be null.
Expand All @@ -63,7 +63,7 @@ internal class ComposeWorkflowImpl<PropsT, OutputT : Any>(
renderProps: PropsT,
renderState: State<PropsT, OutputT>,
context: RenderContext
): ComposeRendering {
): ComposeScreen {
// The first render pass needs to cache the sink. The sink is reusable, so we can just pass the
// same one every time.
if (renderState.sinkHolder.sink == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import com.squareup.workflow1.StatefulWorkflow
import com.squareup.workflow1.action
import com.squareup.workflow1.parse
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.compose.ComposeRendering
import com.squareup.workflow1.ui.compose.ComposeScreen

/**
* The root workflow of this sample. Manges the current toggle state and passes it to
* [HelloComposeWorkflow].
*/
@OptIn(WorkflowUiExperimentalApi::class)
object HelloWorkflow : StatefulWorkflow<Unit, State, Nothing, ComposeRendering>() {
object HelloWorkflow : StatefulWorkflow<Unit, State, Nothing, ComposeScreen>() {
enum class State {
Hello,
Goodbye;
Expand All @@ -40,7 +40,7 @@ object HelloWorkflow : StatefulWorkflow<Unit, State, Nothing, ComposeRendering>(
renderProps: Unit,
renderState: State,
context: RenderContext
): ComposeRendering =
): ComposeScreen =
context.renderChild(HelloComposeWorkflow, renderState.name) { helloAction }

override fun snapshotState(state: State): Snapshot = Snapshot.of(if (state == Hello) 1 else 0)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
@file:Suppress("DEPRECATION", "FunctionName")
@file:OptIn(WorkflowUiExperimentalApi::class)

package com.squareup.sample.compose.inlinerendering
Expand All @@ -20,14 +19,14 @@ import androidx.compose.ui.tooling.preview.Preview
import com.squareup.workflow1.Snapshot
import com.squareup.workflow1.StatefulWorkflow
import com.squareup.workflow1.parse
import com.squareup.workflow1.ui.AndroidViewRendering
import com.squareup.workflow1.ui.AndroidScreen
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.compose.ComposeRendering
import com.squareup.workflow1.ui.compose.ComposeScreen
import com.squareup.workflow1.ui.compose.WorkflowRendering
import com.squareup.workflow1.ui.compose.renderAsState

object InlineRenderingWorkflow : StatefulWorkflow<Unit, Int, Nothing, AndroidViewRendering<*>>() {
object InlineRenderingWorkflow : StatefulWorkflow<Unit, Int, Nothing, AndroidScreen<*>>() {

override fun initialState(
props: Unit,
Expand All @@ -38,7 +37,7 @@ object InlineRenderingWorkflow : StatefulWorkflow<Unit, Int, Nothing, AndroidVie
renderProps: Unit,
renderState: Int,
context: RenderContext
): AndroidViewRendering<*> = ComposeRendering {
): AndroidScreen<*> = ComposeScreen {
Box {
Button(onClick = context.eventHandler { state += 1 }) {
Text("Counter: ")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.squareup.sample.compose.databinding.LegacyViewBinding
import com.squareup.sample.compose.nestedrenderings.RecursiveWorkflow.LegacyRendering
import com.squareup.workflow1.ui.LayoutRunner
import com.squareup.workflow1.ui.LayoutRunner.Companion.bind
import com.squareup.workflow1.ui.ScreenViewFactory
import com.squareup.workflow1.ui.ScreenViewRunner
import com.squareup.workflow1.ui.ScreenViewRunner.Companion.bind
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.ViewFactory
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.compose.tooling.Preview

/**
* A [LayoutRunner] that renders [LegacyRendering]s using the legacy view framework.
* A [ScreenViewRunner] that renders [LegacyRendering]s using the legacy view framework.
*/
@OptIn(WorkflowUiExperimentalApi::class)
class LegacyRunner(private val binding: LegacyViewBinding) : LayoutRunner<LegacyRendering> {
class LegacyRunner(private val binding: LegacyViewBinding) : ScreenViewRunner<LegacyRendering> {

override fun showRendering(
rendering: LegacyRendering,
Expand All @@ -28,7 +28,7 @@ class LegacyRunner(private val binding: LegacyViewBinding) : LayoutRunner<Legacy
binding.stub.update(rendering.rendering, viewEnvironment)
}

companion object : ViewFactory<LegacyRendering> by bind(
companion object : ScreenViewFactory<LegacyRendering> by bind(
LegacyViewBinding::inflate, ::LegacyRunner
)
}
Expand All @@ -37,7 +37,7 @@ class LegacyRunner(private val binding: LegacyViewBinding) : LayoutRunner<Legacy
@Preview(widthDp = 200, heightDp = 150, showBackground = true)
@Composable private fun LegacyRunnerPreview() {
LegacyRunner.Preview(
rendering = LegacyRendering("child"),
rendering = LegacyRendering(StringRendering("child")),
placeholderModifier = Modifier.fillMaxSize()
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.tooling.preview.Preview
import com.squareup.sample.compose.R
import com.squareup.sample.compose.nestedrenderings.RecursiveWorkflow.Rendering
import com.squareup.workflow1.ui.Screen
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.compose.WorkflowRendering
import com.squareup.workflow1.ui.compose.composeViewFactory
import com.squareup.workflow1.ui.compose.composeScreenViewFactory
import com.squareup.workflow1.ui.compose.tooling.Preview

/**
Expand All @@ -38,7 +39,7 @@ val LocalBackgroundColor = compositionLocalOf<Color> { error("No background colo
* A `ViewFactory` that renders [RecursiveWorkflow.Rendering]s.
*/
@OptIn(WorkflowUiExperimentalApi::class)
val RecursiveViewFactory = composeViewFactory<Rendering> { rendering, viewEnvironment ->
val RecursiveViewFactory = composeScreenViewFactory<Rendering> { rendering, viewEnvironment ->
// Every child should be drawn with a slightly-darker background color.
val color = LocalBackgroundColor.current
val childColor = remember(color) {
Expand Down Expand Up @@ -75,9 +76,9 @@ val RecursiveViewFactory = composeViewFactory<Rendering> { rendering, viewEnviro
RecursiveViewFactory.Preview(
Rendering(
children = listOf(
"foo",
StringRendering("foo"),
Rendering(
children = listOf("bar"),
children = listOf(StringRendering("bar")),
onAddChildClicked = {}, onResetClicked = {}
)
),
Expand All @@ -90,7 +91,7 @@ val RecursiveViewFactory = composeViewFactory<Rendering> { rendering, viewEnviro

@OptIn(WorkflowUiExperimentalApi::class)
@Composable private fun Children(
children: List<Any>,
children: List<Screen>,
viewEnvironment: ViewEnvironment,
modifier: Modifier
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import com.squareup.workflow1.Snapshot
import com.squareup.workflow1.StatefulWorkflow
import com.squareup.workflow1.action
import com.squareup.workflow1.renderChild
import com.squareup.workflow1.ui.Screen
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi

/**
* A simple workflow that produces [Rendering]s of zero or more children.
Expand All @@ -16,7 +18,8 @@ import com.squareup.workflow1.renderChild
* to force it to go through the legacy view layer. This way this sample both demonstrates pass-
* through Composable renderings as well as adapting in both directions.
*/
object RecursiveWorkflow : StatefulWorkflow<Unit, State, Nothing, Any>() {
@OptIn(WorkflowUiExperimentalApi::class)
object RecursiveWorkflow : StatefulWorkflow<Unit, State, Nothing, Screen>() {

data class State(val children: Int = 0)

Expand All @@ -28,15 +31,15 @@ object RecursiveWorkflow : StatefulWorkflow<Unit, State, Nothing, Any>() {
* @param onResetClicked Resets [children] to an empty list.
*/
data class Rendering(
val children: List<Any>,
val children: List<Screen>,
val onAddChildClicked: () -> Unit,
val onResetClicked: () -> Unit
)
) : Screen

/**
* Wrapper around a [Rendering] that will be implemented using a legacy view.
*/
data class LegacyRendering(val rendering: Any)
data class LegacyRendering(val rendering: Screen) : Screen

override fun initialState(
props: Unit,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.squareup.sample.compose.nestedrenderings

import com.squareup.workflow1.ui.Screen
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi

@OptIn(WorkflowUiExperimentalApi::class)
data class StringRendering(val value: String) : Screen
Loading