Skip to content

Commit f520e16

Browse files
committed
wip: ViewRegistry overhaul, ViewRendering, ModalRendering
Builds the simpler, more flexible scheme for modals proposed in #195. Only AlertDialog takes advantage of it so far, and only the `hellobackbutton` and `helloworkflow` samples are ported. closes #195 * We introduce the `ViewRendering` and `ModalRendering` interfaces, similar in sprit to `AnyScreen` in Swift. * `ViewRegistry` changes to be able to hold a collection of more arbitrary entry types, not just `ViewFactory`. * Its `buildView` method is deprecated. * Once we delete that method, we should be able to move `ViewRegistry` over to the non-Android, core UI module. * There are three implementations of `ViewRegistry.Entry` * Our old friend `ViewFactory<T: Any>`, now deprecated. * `ViewBuilder<T: ViewRendering>`, which replaces `ViewFactory` * `DialogBuilder<T: ModalRendering>` * Extension method `ViewRendering.buildView()` replaces `ViewRegistry.buildView()`. We also introduce `ModalRendering.buildDialog()`. * These methods find the appropriate builder in `ViewRegistry`, based on the concrete type of the rendering, just like `ViewRegistry.buildView()` did. * The new ability of `ViewRegistry` to hold arbitrary entries means that we can add as many rendering:view-machinery pairings as we want to. Maybe cleans up Compose integration? * `LayoutRunner<T: Any>` is deprecated, replaced by `ViewRunner<T: ViewRendering>`. That's going to be a tedious migration for existing `LayoutRunner` implementations, but it avoids a huge breaking change — the new mechanism works in parallel with the deprecated one. * `WorkflowViewStub.display(rendering: ViewRendering)` replaces `WorkflowViewStub.update(rendering: Any)`, now deprecated. But the latter is able to delegate to the former so incremental migration is possible.
1 parent 17af831 commit f520e16

File tree

43 files changed

+1277
-476
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1277
-476
lines changed
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
package com.squareup.sample.container
22

3+
import com.squareup.workflow1.ui.DecorativeViewBuilder
34
import com.squareup.workflow1.ui.DecorativeViewFactory
5+
import com.squareup.workflow1.ui.ViewBuilder
46
import com.squareup.workflow1.ui.ViewFactory
57
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
68
import com.squareup.workflow1.ui.backPressedHandler
79

810
/**
9-
* [ViewFactory] that performs the work required by [BackButtonScreen].
11+
* [ViewFactory] that performs the work required by [BackButtonViewRendering].
1012
*/
1113
@WorkflowUiExperimentalApi
12-
object BackButtonViewFactory : ViewFactory<BackButtonScreen<*>>
13-
by DecorativeViewFactory(
14-
type = BackButtonScreen::class,
14+
object BackButtonViewBuilder : ViewBuilder<BackButtonViewRendering<*>>
15+
by DecorativeViewBuilder(
16+
type = BackButtonViewRendering::class,
1517
map = { outer -> outer.wrapped },
1618
doShowRendering = { view, innerShowRendering, outerRendering, viewEnvironment ->
1719
if (!outerRendering.override) {
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,6 @@
1-
/*
2-
* Copyright 2020 Square Inc.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
161
package com.squareup.sample.container
172

3+
import com.squareup.workflow1.ui.ViewRendering
184
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
195

206
/**
@@ -31,8 +17,8 @@ import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
3117
* is pressed, or null to set no handler. Defaults to `null`.
3218
*/
3319
@WorkflowUiExperimentalApi
34-
data class BackButtonScreen<W : Any>(
20+
data class BackButtonViewRendering<W : ViewRendering>(
3521
val wrapped: W,
3622
val override: Boolean = false,
3723
val onBackPressed: (() -> Unit)? = null
38-
)
24+
) : ViewRendering

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ import com.squareup.workflow1.ui.ViewRegistry
2323

2424
@OptIn(WorkflowUiExperimentalApi::class)
2525
val SampleContainers = ViewRegistry(
26-
BackButtonViewFactory, OverviewDetailContainer, PanelContainer, ScrimContainer
26+
OverviewDetailContainer, PanelContainer, ScrimContainer
2727
)

samples/containers/android/src/main/java/com/squareup/sample/container/panel/ScrimContainer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import com.squareup.workflow1.ui.bindShowRendering
3131
* A view that renders only its first child, behind a smoke scrim if
3232
* [isDimmed] is true (tablets only). Other children are ignored.
3333
*
34-
* Able to [render][com.squareup.workflow1.ui.showRendering] [ScrimContainerScreen].
34+
* Able to [render][com.squareup.workflow1.ui.display] [ScrimContainerScreen].
3535
*/
3636
class ScrimContainer @JvmOverloads constructor(
3737
context: Context,

samples/containers/hello-back-button/src/main/java/com/squareup/sample/hellobackbutton/AreYouSureWorkflow.kt

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,7 @@
1-
/*
2-
* Copyright 2020 Square Inc.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
161
package com.squareup.sample.hellobackbutton
172

183
import android.os.Parcelable
19-
import com.squareup.sample.container.BackButtonScreen
4+
import com.squareup.sample.container.BackButtonViewRendering
205
import com.squareup.sample.hellobackbutton.AreYouSureWorkflow.Finished
216
import com.squareup.sample.hellobackbutton.AreYouSureWorkflow.State
227
import com.squareup.sample.hellobackbutton.AreYouSureWorkflow.State.Quitting
@@ -25,23 +10,27 @@ import com.squareup.workflow1.Snapshot
2510
import com.squareup.workflow1.StatefulWorkflow
2611
import com.squareup.workflow1.WorkflowAction.Companion.noAction
2712
import com.squareup.workflow1.action
13+
import com.squareup.workflow1.ui.AlertModalRendering
14+
import com.squareup.workflow1.ui.AlertModalRendering.Button.NEGATIVE
15+
import com.squareup.workflow1.ui.AlertModalRendering.Button.POSITIVE
16+
import com.squareup.workflow1.ui.AlertModalRendering.Event.ButtonClicked
17+
import com.squareup.workflow1.ui.AlertModalRendering.Event.Canceled
18+
import com.squareup.workflow1.ui.ModalContainerViewRendering
2819
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
29-
import com.squareup.workflow1.ui.modal.AlertContainerScreen
30-
import com.squareup.workflow1.ui.modal.AlertScreen
31-
import com.squareup.workflow1.ui.modal.AlertScreen.Button.NEGATIVE
32-
import com.squareup.workflow1.ui.modal.AlertScreen.Button.POSITIVE
33-
import com.squareup.workflow1.ui.modal.AlertScreen.Event.ButtonClicked
34-
import com.squareup.workflow1.ui.modal.AlertScreen.Event.Canceled
3520
import com.squareup.workflow1.ui.toParcelable
3621
import com.squareup.workflow1.ui.toSnapshot
3722
import kotlinx.android.parcel.Parcelize
3823

24+
@OptIn(WorkflowUiExperimentalApi::class)
25+
private typealias Rendering = ModalContainerViewRendering<*, AlertModalRendering>
26+
3927
/**
4028
* Wraps [HelloBackButtonWorkflow] to (sometimes) pop a confirmation dialog when the back
4129
* button is pressed.
4230
*/
4331
@OptIn(WorkflowUiExperimentalApi::class)
44-
object AreYouSureWorkflow : StatefulWorkflow<Unit, State, Finished, AlertContainerScreen<*>>() {
32+
object AreYouSureWorkflow :
33+
StatefulWorkflow<Unit, State, Finished, Rendering>() {
4534
override fun initialState(
4635
props: Unit,
4736
snapshot: Snapshot?
@@ -59,13 +48,13 @@ object AreYouSureWorkflow : StatefulWorkflow<Unit, State, Finished, AlertContain
5948
props: Unit,
6049
state: State,
6150
context: RenderContext
62-
): AlertContainerScreen<*> {
51+
): Rendering {
6352
val ableBakerCharlie = context.renderChild(HelloBackButtonWorkflow, Unit) { noAction() }
6453

6554
return when (state) {
6655
Running -> {
67-
AlertContainerScreen(
68-
BackButtonScreen(ableBakerCharlie) {
56+
ModalContainerViewRendering(
57+
BackButtonViewRendering(ableBakerCharlie) {
6958
// While we always provide a back button handler, by default the view code
7059
// associated with BackButtonScreen ignores ours if the view created for the
7160
// wrapped rendering sets a handler of its own. (Set BackButtonScreen.override
@@ -75,7 +64,7 @@ object AreYouSureWorkflow : StatefulWorkflow<Unit, State, Finished, AlertContain
7564
)
7665
}
7766
Quitting -> {
78-
val dialog = AlertScreen(
67+
val dialog = AlertModalRendering(
7968
buttons = mapOf(
8069
POSITIVE to "I'm Positive",
8170
NEGATIVE to "Negatory"
@@ -94,7 +83,7 @@ object AreYouSureWorkflow : StatefulWorkflow<Unit, State, Finished, AlertContain
9483
}
9584
)
9685

97-
AlertContainerScreen(ableBakerCharlie, dialog)
86+
ModalContainerViewRendering(ableBakerCharlie, dialog)
9887
}
9988
}
10089
}

samples/containers/hello-back-button/src/main/java/com/squareup/sample/hellobackbutton/HelloBackButtonActivity.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,17 @@ package com.squareup.sample.hellobackbutton
1717

1818
import android.os.Bundle
1919
import androidx.appcompat.app.AppCompatActivity
20-
import com.squareup.sample.container.SampleContainers
20+
import com.squareup.sample.container.BackButtonViewBuilder
2121
import com.squareup.workflow1.SimpleLoggingWorkflowInterceptor
2222
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
2323
import com.squareup.workflow1.ui.ViewRegistry
2424
import com.squareup.workflow1.ui.WorkflowRunner
25-
import com.squareup.workflow1.ui.modal.AlertContainer
2625
import com.squareup.workflow1.ui.plus
2726
import com.squareup.workflow1.ui.setContentWorkflow
2827

2928
@OptIn(WorkflowUiExperimentalApi::class)
3029
private val viewRegistry =
31-
ViewRegistry(HelloBackButtonLayoutRunner) + SampleContainers + AlertContainer
30+
ViewRegistry(HelloBackButtonViewRunner) + BackButtonViewBuilder
3231

3332
class HelloBackButtonActivity : AppCompatActivity() {
3433
@OptIn(WorkflowUiExperimentalApi::class)

samples/containers/hello-back-button/src/main/java/com/squareup/sample/hellobackbutton/HelloBackButtonLayoutRunner.kt

Lines changed: 0 additions & 46 deletions
This file was deleted.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.squareup.sample.hellobackbutton
2+
3+
import android.view.View
4+
import android.widget.TextView
5+
import com.squareup.sample.hellobackbutton.HelloBackButtonWorkflow.Rendering
6+
import com.squareup.sample.hellobackbutton.R.id
7+
import com.squareup.sample.hellobackbutton.R.layout
8+
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
9+
import com.squareup.workflow1.ui.ViewBuilder
10+
import com.squareup.workflow1.ui.ViewEnvironment
11+
import com.squareup.workflow1.ui.ViewRunner
12+
import com.squareup.workflow1.ui.ViewRunner.Companion.bind
13+
import com.squareup.workflow1.ui.backPressedHandler
14+
15+
@OptIn(WorkflowUiExperimentalApi::class)
16+
internal class HelloBackButtonViewRunner(view: View) : ViewRunner<Rendering> {
17+
private val messageView: TextView = view.findViewById(id.hello_message)
18+
19+
override fun showRendering(
20+
rendering: Rendering,
21+
viewEnvironment: ViewEnvironment
22+
) {
23+
messageView.text = rendering.message
24+
messageView.setOnClickListener { rendering.onClick() }
25+
messageView.backPressedHandler = rendering.onBackPressed
26+
}
27+
28+
companion object : ViewBuilder<Rendering> by bind(
29+
layout.hello_back_button_layout, ::HelloBackButtonViewRunner
30+
)
31+
}

samples/containers/hello-back-button/src/main/java/com/squareup/sample/hellobackbutton/HelloBackButtonWorkflow.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,33 @@
1616
package com.squareup.sample.hellobackbutton
1717

1818
import android.os.Parcelable
19-
import com.squareup.sample.hellobackbutton.HelloBackButtonWorkflow.Rendering
2019
import com.squareup.sample.hellobackbutton.HelloBackButtonWorkflow.State
2120
import com.squareup.sample.hellobackbutton.HelloBackButtonWorkflow.State.Able
2221
import com.squareup.sample.hellobackbutton.HelloBackButtonWorkflow.State.Baker
2322
import com.squareup.sample.hellobackbutton.HelloBackButtonWorkflow.State.Charlie
2423
import com.squareup.workflow1.Snapshot
2524
import com.squareup.workflow1.StatefulWorkflow
2625
import com.squareup.workflow1.action
26+
import com.squareup.workflow1.ui.ViewRendering
27+
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
2728
import com.squareup.workflow1.ui.toParcelable
2829
import com.squareup.workflow1.ui.toSnapshot
2930
import kotlinx.android.parcel.Parcelize
3031

31-
object HelloBackButtonWorkflow : StatefulWorkflow<Unit, State, Nothing, Rendering>() {
32+
@OptIn(WorkflowUiExperimentalApi::class)
33+
object HelloBackButtonWorkflow : StatefulWorkflow<Unit, State, Nothing, ViewRendering>() {
3234
@Parcelize
3335
enum class State : Parcelable {
3436
Able,
3537
Baker,
3638
Charlie;
3739
}
3840

39-
data class Rendering(
41+
internal data class Rendering(
4042
val message: String,
4143
val onClick: () -> Unit,
4244
val onBackPressed: (() -> Unit)?
43-
)
45+
) : ViewRendering
4446

4547
override fun initialState(
4648
props: Unit,
@@ -51,7 +53,7 @@ object HelloBackButtonWorkflow : StatefulWorkflow<Unit, State, Nothing, Renderin
5153
props: Unit,
5254
state: State,
5355
context: RenderContext
54-
): Rendering {
56+
): ViewRendering {
5557
return Rendering(
5658
message = "$state",
5759
onClick = { context.actionSink.send(advance) },

samples/hello-workflow/src/main/java/com/squareup/sample/helloworkflow/HelloViewFactory.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ import com.squareup.sample.helloworkflow.HelloWorkflow.Rendering
1919
import com.squareup.sample.helloworkflow.databinding.HelloGoodbyeLayoutBinding
2020
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
2121
import com.squareup.workflow1.ui.LayoutRunner
22+
import com.squareup.workflow1.ui.ViewBuilder
2223
import com.squareup.workflow1.ui.ViewFactory
24+
import com.squareup.workflow1.ui.ViewRunner
2325

2426
@OptIn(WorkflowUiExperimentalApi::class)
25-
val HelloViewFactory: ViewFactory<Rendering> =
26-
LayoutRunner.bind(HelloGoodbyeLayoutBinding::inflate) { rendering, _ ->
27+
val HelloViewBuilder: ViewBuilder<Rendering> =
28+
ViewRunner.bind(HelloGoodbyeLayoutBinding::inflate) { rendering, _ ->
2729
helloMessage.text = rendering.message
2830
helloMessage.setOnClickListener { rendering.onClick() }
2931
}

0 commit comments

Comments
 (0)