Skip to content

Commit 09bf09f

Browse files
committed
BREAKING: ViewRegistry.Key allows multiple factory types per rendering type
Paves the way for parallel Classic and Compose implementations of wrappers like `NamedScreen`, to fix #546. Ironically, breaks Compose support in the process, but that is fixed by the next commit.
1 parent 97b1b70 commit 09bf09f

File tree

15 files changed

+202
-76
lines changed

15 files changed

+202
-76
lines changed

workflow-ui/compose/api/compose.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public abstract class com/squareup/workflow1/ui/compose/ComposeScreenViewFactory
1616
public fun <init> ()V
1717
public abstract fun Content (Lcom/squareup/workflow1/ui/Screen;Lcom/squareup/workflow1/ui/ViewEnvironment;Landroidx/compose/runtime/Composer;I)V
1818
public final fun buildView (Lcom/squareup/workflow1/ui/Screen;Lcom/squareup/workflow1/ui/ViewEnvironment;Landroid/content/Context;Landroid/view/ViewGroup;)Lcom/squareup/workflow1/ui/ScreenViewHolder;
19+
public final fun getKey ()Lcom/squareup/workflow1/ui/ViewRegistry$Key;
1920
}
2021

2122
public final class com/squareup/workflow1/ui/compose/ComposeScreenViewFactoryKt {

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.squareup.workflow1.ui.Screen
1111
import com.squareup.workflow1.ui.ScreenViewFactory
1212
import com.squareup.workflow1.ui.ScreenViewHolder
1313
import com.squareup.workflow1.ui.ViewEnvironment
14+
import com.squareup.workflow1.ui.ViewRegistry.Key
1415
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
1516
import kotlin.reflect.KClass
1617

@@ -113,6 +114,10 @@ internal fun <RenderingT : Screen> composeScreenViewFactory(
113114
@WorkflowUiExperimentalApi
114115
public abstract class ComposeScreenViewFactory<RenderingT : Screen> :
115116
ScreenViewFactory<RenderingT> {
117+
118+
final override val key: Key<RenderingT, ScreenViewFactory<*>>
119+
get() = Key(type, ComposeScreenViewFactory::class)
120+
116121
/**
117122
* The composable content of this [ScreenViewFactory]. This method will be called
118123
* any time [rendering] or [viewEnvironment] change. It is the Compose-based analogue of

workflow-ui/core-android/api/core-android.api

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public abstract interface class com/squareup/workflow1/ui/AndroidScreen : com/sq
1414
public final class com/squareup/workflow1/ui/LayoutScreenViewFactory : com/squareup/workflow1/ui/ScreenViewFactory {
1515
public fun <init> (Lkotlin/reflect/KClass;ILkotlin/jvm/functions/Function1;)V
1616
public fun buildView (Lcom/squareup/workflow1/ui/Screen;Lcom/squareup/workflow1/ui/ViewEnvironment;Landroid/content/Context;Landroid/view/ViewGroup;)Lcom/squareup/workflow1/ui/ScreenViewHolder;
17+
public fun getKey ()Lcom/squareup/workflow1/ui/ViewRegistry$Key;
1718
public fun getType ()Lkotlin/reflect/KClass;
1819
}
1920

@@ -39,13 +40,16 @@ public final class com/squareup/workflow1/ui/ParcelableTextController$CREATOR :
3940
public abstract interface class com/squareup/workflow1/ui/ScreenViewFactory : com/squareup/workflow1/ui/ViewRegistry$Entry {
4041
public static final field Companion Lcom/squareup/workflow1/ui/ScreenViewFactory$Companion;
4142
public abstract fun buildView (Lcom/squareup/workflow1/ui/Screen;Lcom/squareup/workflow1/ui/ViewEnvironment;Landroid/content/Context;Landroid/view/ViewGroup;)Lcom/squareup/workflow1/ui/ScreenViewHolder;
43+
public abstract fun getKey ()Lcom/squareup/workflow1/ui/ViewRegistry$Key;
44+
public abstract fun getType ()Lkotlin/reflect/KClass;
4245
}
4346

4447
public final class com/squareup/workflow1/ui/ScreenViewFactory$Companion {
4548
}
4649

4750
public final class com/squareup/workflow1/ui/ScreenViewFactory$DefaultImpls {
4851
public static synthetic fun buildView$default (Lcom/squareup/workflow1/ui/ScreenViewFactory;Lcom/squareup/workflow1/ui/Screen;Lcom/squareup/workflow1/ui/ViewEnvironment;Landroid/content/Context;Landroid/view/ViewGroup;ILjava/lang/Object;)Lcom/squareup/workflow1/ui/ScreenViewHolder;
52+
public static fun getKey (Lcom/squareup/workflow1/ui/ScreenViewFactory;)Lcom/squareup/workflow1/ui/ViewRegistry$Key;
4953
}
5054

5155
public abstract interface class com/squareup/workflow1/ui/ScreenViewFactoryFinder {
@@ -101,6 +105,7 @@ public final class com/squareup/workflow1/ui/TextControllerControlEditTextKt {
101105
public final class com/squareup/workflow1/ui/ViewBindingScreenViewFactory : com/squareup/workflow1/ui/ScreenViewFactory {
102106
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;)V
103107
public fun buildView (Lcom/squareup/workflow1/ui/Screen;Lcom/squareup/workflow1/ui/ViewEnvironment;Landroid/content/Context;Landroid/view/ViewGroup;)Lcom/squareup/workflow1/ui/ScreenViewHolder;
108+
public fun getKey ()Lcom/squareup/workflow1/ui/ViewRegistry$Key;
104109
public fun getType ()Lkotlin/reflect/KClass;
105110
}
106111

@@ -283,11 +288,17 @@ public final class com/squareup/workflow1/ui/navigation/LayeredDialogSessions$Sa
283288
public abstract interface class com/squareup/workflow1/ui/navigation/OverlayDialogFactory : com/squareup/workflow1/ui/ViewRegistry$Entry {
284289
public static final field Companion Lcom/squareup/workflow1/ui/navigation/OverlayDialogFactory$Companion;
285290
public abstract fun buildDialog (Lcom/squareup/workflow1/ui/navigation/Overlay;Lcom/squareup/workflow1/ui/ViewEnvironment;Landroid/content/Context;)Lcom/squareup/workflow1/ui/navigation/OverlayDialogHolder;
291+
public abstract fun getKey ()Lcom/squareup/workflow1/ui/ViewRegistry$Key;
292+
public abstract fun getType ()Lkotlin/reflect/KClass;
286293
}
287294

288295
public final class com/squareup/workflow1/ui/navigation/OverlayDialogFactory$Companion {
289296
}
290297

298+
public final class com/squareup/workflow1/ui/navigation/OverlayDialogFactory$DefaultImpls {
299+
public static fun getKey (Lcom/squareup/workflow1/ui/navigation/OverlayDialogFactory;)Lcom/squareup/workflow1/ui/ViewRegistry$Key;
300+
}
301+
291302
public abstract interface class com/squareup/workflow1/ui/navigation/OverlayDialogFactoryFinder {
292303
public static final field Companion Lcom/squareup/workflow1/ui/navigation/OverlayDialogFactoryFinder$Companion;
293304
public abstract fun getDialogFactoryForRendering (Lcom/squareup/workflow1/ui/ViewEnvironment;Lcom/squareup/workflow1/ui/navigation/Overlay;)Lcom/squareup/workflow1/ui/navigation/OverlayDialogFactory;

workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/ScreenViewFactory.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import androidx.viewbinding.ViewBinding
99
import com.squareup.workflow1.ui.ScreenViewFactory.Companion.fromCode
1010
import com.squareup.workflow1.ui.ScreenViewFactory.Companion.fromLayout
1111
import com.squareup.workflow1.ui.ScreenViewFactory.Companion.fromViewBinding
12+
import com.squareup.workflow1.ui.ViewRegistry.Key
13+
import kotlin.reflect.KClass
1214

1315
@WorkflowUiExperimentalApi
1416
public typealias ViewBindingInflater<BindingT> = (LayoutInflater, ViewGroup?, Boolean) -> BindingT
@@ -48,6 +50,10 @@ public typealias ViewBindingInflater<BindingT> = (LayoutInflater, ViewGroup?, Bo
4850
*/
4951
@WorkflowUiExperimentalApi
5052
public interface ScreenViewFactory<in ScreenT : Screen> : ViewRegistry.Entry<ScreenT> {
53+
public val type: KClass<in ScreenT>
54+
55+
override val key: Key<ScreenT, ScreenViewFactory<*>> get() = Key(type, ScreenViewFactory::class)
56+
5157
/**
5258
* It is rare to call this method directly. Instead the most common path is to pass [Screen]
5359
* instances to [WorkflowViewStub.show], which will apply the [ScreenViewFactory] machinery for

workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/ScreenViewFactoryFinder.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.squareup.workflow1.ui
22

33
import com.squareup.workflow1.ui.ScreenViewFactory.Companion.forWrapper
4+
import com.squareup.workflow1.ui.ViewRegistry.Key
45
import com.squareup.workflow1.ui.navigation.BackStackScreen
56
import com.squareup.workflow1.ui.navigation.BackStackScreenViewFactory
67
import com.squareup.workflow1.ui.navigation.BodyAndOverlaysContainer
@@ -53,7 +54,8 @@ public interface ScreenViewFactoryFinder {
5354
environment: ViewEnvironment,
5455
rendering: ScreenT
5556
): ScreenViewFactory<ScreenT> {
56-
val entry = environment[ViewRegistry].getEntryFor(rendering::class)
57+
val entry = environment[ViewRegistry]
58+
.getEntryFor(Key(rendering::class, ScreenViewFactory::class))
5759

5860
@Suppress("UNCHECKED_CAST")
5961
return (entry as? ScreenViewFactory<ScreenT>)

workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/navigation/OverlayDialogFactory.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import android.app.Dialog
44
import android.content.Context
55
import com.squareup.workflow1.ui.ViewEnvironment
66
import com.squareup.workflow1.ui.ViewRegistry
7+
import com.squareup.workflow1.ui.ViewRegistry.Key
78
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
9+
import kotlin.reflect.KClass
810

911
/**
1012
* Factory for [Dialog] instances that can show renderings of type [OverlayT].
@@ -64,6 +66,10 @@ import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
6466
*/
6567
@WorkflowUiExperimentalApi
6668
public interface OverlayDialogFactory<OverlayT : Overlay> : ViewRegistry.Entry<OverlayT> {
69+
public val type: KClass<in OverlayT>
70+
71+
override val key: Key<OverlayT, *> get() = Key(type, OverlayDialogFactory::class)
72+
6773
/** Builds a [Dialog], but does not show it. */
6874
public fun buildDialog(
6975
initialRendering: OverlayT,

workflow-ui/core-android/src/main/java/com/squareup/workflow1/ui/navigation/OverlayDialogFactoryFinder.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.squareup.workflow1.ui.Screen
44
import com.squareup.workflow1.ui.ViewEnvironment
55
import com.squareup.workflow1.ui.ViewEnvironmentKey
66
import com.squareup.workflow1.ui.ViewRegistry
7+
import com.squareup.workflow1.ui.ViewRegistry.Key
78
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
89

910
/**
@@ -17,7 +18,8 @@ public interface OverlayDialogFactoryFinder {
1718
environment: ViewEnvironment,
1819
rendering: OverlayT
1920
): OverlayDialogFactory<OverlayT> {
20-
val entry = environment[ViewRegistry].getEntryFor(rendering::class)
21+
val entry = environment[ViewRegistry]
22+
.getEntryFor(Key(rendering::class, OverlayDialogFactory::class))
2123

2224
@Suppress("UNCHECKED_CAST")
2325
return entry as? OverlayDialogFactory<OverlayT>

workflow-ui/core-android/src/test/java/com/squareup/workflow1/ui/ScreenViewFactoryTest.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.view.ViewGroup
55
import com.google.common.truth.Truth.assertThat
66
import com.squareup.workflow1.ui.ScreenViewFactory.Companion.forWrapper
77
import com.squareup.workflow1.ui.ViewRegistry.Entry
8+
import com.squareup.workflow1.ui.ViewRegistry.Key
89
import org.junit.Test
910
import org.mockito.kotlin.mock
1011
import kotlin.reflect.KClass
@@ -16,9 +17,10 @@ internal class ScreenViewFactoryTest {
1617
@Test
1718
fun missingBindingMessage_isUseful() {
1819
val emptyReg = object : ViewRegistry {
19-
override val keys: Set<KClass<*>> = emptySet()
20-
override fun <RenderingT : Any> getEntryFor(
21-
renderingType: KClass<out RenderingT>
20+
21+
override val keys: Set<Key<*, *>> = emptySet()
22+
override fun <RenderingT : Any, FactoryT : Any> getEntryFor(
23+
key: Key<RenderingT, FactoryT>
2224
): Entry<RenderingT>? = null
2325
}
2426
val env = ViewEnvironment.EMPTY + emptyReg

workflow-ui/core-common/api/core-common.api

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public abstract class com/squareup/workflow1/ui/ViewEnvironmentKey {
9494

9595
public abstract interface class com/squareup/workflow1/ui/ViewRegistry {
9696
public static final field Companion Lcom/squareup/workflow1/ui/ViewRegistry$Companion;
97-
public abstract fun getEntryFor (Lkotlin/reflect/KClass;)Lcom/squareup/workflow1/ui/ViewRegistry$Entry;
97+
public abstract fun getEntryFor (Lcom/squareup/workflow1/ui/ViewRegistry$Key;)Lcom/squareup/workflow1/ui/ViewRegistry$Entry;
9898
public abstract fun getKeys ()Ljava/util/Set;
9999
}
100100

@@ -106,7 +106,16 @@ public final class com/squareup/workflow1/ui/ViewRegistry$Companion : com/square
106106
}
107107

108108
public abstract interface class com/squareup/workflow1/ui/ViewRegistry$Entry {
109-
public abstract fun getType ()Lkotlin/reflect/KClass;
109+
public abstract fun getKey ()Lcom/squareup/workflow1/ui/ViewRegistry$Key;
110+
}
111+
112+
public final class com/squareup/workflow1/ui/ViewRegistry$Key {
113+
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;)V
114+
public fun equals (Ljava/lang/Object;)Z
115+
public final fun getFactoryType ()Lkotlin/reflect/KClass;
116+
public final fun getRenderingType ()Lkotlin/reflect/KClass;
117+
public fun hashCode ()I
118+
public fun toString ()Ljava/lang/String;
110119
}
111120

112121
public final class com/squareup/workflow1/ui/ViewRegistryKt {

workflow-ui/core-common/src/main/java/com/squareup/workflow1/ui/CompositeViewRegistry.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.squareup.workflow1.ui
22

33
import com.squareup.workflow1.ui.ViewRegistry.Entry
4-
import kotlin.reflect.KClass
4+
import com.squareup.workflow1.ui.ViewRegistry.Key
55

66
/**
77
* A [ViewRegistry] that contains only other registries and delegates to their [getEntryFor]
@@ -20,26 +20,26 @@ import kotlin.reflect.KClass
2020
*/
2121
@WorkflowUiExperimentalApi
2222
internal class CompositeViewRegistry private constructor(
23-
private val registriesByKey: Map<KClass<*>, ViewRegistry>
23+
private val registriesByKey: Map<Key<*, *>, ViewRegistry>
2424
) : ViewRegistry {
2525

2626
constructor (vararg registries: ViewRegistry) : this(mergeRegistries(*registries))
2727

28-
override val keys: Set<KClass<*>> get() = registriesByKey.keys
28+
override val keys: Set<Key<*, *>> get() = registriesByKey.keys
2929

30-
override fun <RenderingT : Any> getEntryFor(
31-
renderingType: KClass<out RenderingT>
32-
): Entry<RenderingT>? = registriesByKey[renderingType]?.getEntryFor(renderingType)
30+
override fun <RenderingT : Any, FactoryT : Any> getEntryFor(
31+
key: Key<RenderingT, FactoryT>
32+
): Entry<RenderingT>? = registriesByKey[key]?.getEntryFor(key)
3333

3434
override fun toString(): String {
3535
return "CompositeViewRegistry(${registriesByKey.values.toSet().map { it.toString() }})"
3636
}
3737

3838
companion object {
39-
private fun mergeRegistries(vararg registries: ViewRegistry): Map<KClass<*>, ViewRegistry> {
40-
val registriesByKey = mutableMapOf<KClass<*>, ViewRegistry>()
39+
private fun mergeRegistries(vararg registries: ViewRegistry): Map<Key<*, *>, ViewRegistry> {
40+
val registriesByKey = mutableMapOf<Key<*, *>, ViewRegistry>()
4141

42-
fun putAllUnique(other: Map<KClass<*>, ViewRegistry>) {
42+
fun putAllUnique(other: Map<Key<*, *>, ViewRegistry>) {
4343
val duplicateKeys = registriesByKey.keys.intersect(other.keys)
4444
require(duplicateKeys.isEmpty()) {
4545
"Must not have duplicate entries: $duplicateKeys. Use merge to replace existing entries."

0 commit comments

Comments
 (0)