Skip to content
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

Friendlier construction API for BackStackScreen #1110

Merged
merged 1 commit into from
Sep 21, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,9 @@ internal class ComposeViewTreeIntegrationTest {
}

private fun WorkflowUiTestActivity.setBackstack(vararg backstack: TestComposeRendering) {
setRendering(BackStackScreen(EmptyRendering, backstack.asList()))
setRendering(
BackStackScreen.fromList(listOf<AndroidScreen<*>>(EmptyRendering) + backstack.asList())
)
}

data class TestOverlay(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ internal class BackStackContainerLifecycleActivity : AbstractLifecycleTestActivi
setRendering(backstack.asList().toBackstackWithBase())

private fun List<TestRendering>.toBackstackWithBase() =
BackStackScreen(BaseRendering, this)
BackStackScreen.fromList(listOf<Screen>(BaseRendering) + this)
}

internal fun ActivityScenario<BackStackContainerLifecycleActivity>.viewForScreen(
Expand Down
7 changes: 7 additions & 0 deletions workflow-ui/core-common/api/core-common.api
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,10 @@ public final class com/squareup/workflow1/ui/container/BackStackConfigKt {
}

public final class com/squareup/workflow1/ui/container/BackStackScreen : com/squareup/workflow1/ui/Container, com/squareup/workflow1/ui/Screen {
public static final field Companion Lcom/squareup/workflow1/ui/container/BackStackScreen$Companion;
public fun <init> (Lcom/squareup/workflow1/ui/Screen;Ljava/util/List;)V
public fun <init> (Lcom/squareup/workflow1/ui/Screen;[Lcom/squareup/workflow1/ui/Screen;)V
public synthetic fun <init> (Ljava/util/List;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun asSequence ()Lkotlin/sequences/Sequence;
public fun equals (Ljava/lang/Object;)Z
public final fun get (I)Lcom/squareup/workflow1/ui/Screen;
Expand All @@ -229,6 +231,11 @@ public final class com/squareup/workflow1/ui/container/BackStackScreen : com/squ
public fun toString ()Ljava/lang/String;
}

public final class com/squareup/workflow1/ui/container/BackStackScreen$Companion {
public final fun fromList (Ljava/util/List;)Lcom/squareup/workflow1/ui/container/BackStackScreen;
public final fun fromListOrNull (Ljava/util/List;)Lcom/squareup/workflow1/ui/container/BackStackScreen;
}

public final class com/squareup/workflow1/ui/container/BackStackScreenKt {
public static final fun toBackStackScreen (Ljava/util/List;)Lcom/squareup/workflow1/ui/container/BackStackScreen;
public static final fun toBackStackScreenOrNull (Ljava/util/List;)Lcom/squareup/workflow1/ui/container/BackStackScreen;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package com.squareup.workflow1.ui.container
import com.squareup.workflow1.ui.Container
import com.squareup.workflow1.ui.Screen
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.container.BackStackScreen.Companion
import com.squareup.workflow1.ui.container.BackStackScreen.Companion.fromList
import com.squareup.workflow1.ui.container.BackStackScreen.Companion.fromListOrNull

/**
* Represents an active screen ([top]), and a set of previously visited screens to which we may
Expand All @@ -13,25 +16,31 @@ import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
*
* UI kits are expected to provide handling for this class by default.
*
* @param bottom the bottom-most entry in the stack
* @param rest the rest of the stack, empty by default
* @see fromList
* @see fromListOrNull
*/
@WorkflowUiExperimentalApi
public class BackStackScreen<StackedT : Screen>(
bottom: StackedT,
rest: List<StackedT>
public class BackStackScreen<StackedT : Screen> private constructor(
public val frames: List<StackedT>
) : Screen, Container<Screen, StackedT> {
/**
* Creates a screen with elements listed from the [bottom] to the top.
*/
public constructor(
bottom: StackedT,
vararg rest: StackedT
) : this(bottom, rest.toList())
) : this(listOf(bottom) + rest)

override fun asSequence(): Sequence<StackedT> = frames.asSequence()
@Deprecated(
"Use fromList",
ReplaceWith("BackStackScreen.fromList(listOf(bottom) + rest)")
)
public constructor(
bottom: StackedT,
rest: List<StackedT>
) : this(listOf(bottom) + rest)

public val frames: List<StackedT> = listOf(bottom) + rest
override fun asSequence(): Sequence<StackedT> = frames.asSequence()

/**
* The active screen.
Expand All @@ -49,7 +58,7 @@ public class BackStackScreen<StackedT : Screen>(
return if (other == null) {
this
} else {
BackStackScreen(frames[0], frames.subList(1, frames.size) + other.frames)
BackStackScreen(frames + other.frames)
}
}

Expand All @@ -75,16 +84,37 @@ public class BackStackScreen<StackedT : Screen>(
override fun toString(): String {
return "${this::class.java.simpleName}($frames)"
}

public companion object {
/**
* Builds a [BackStackScreen] from a non-empty list of [frames].
*
* @throws IllegalArgumentException is [frames] is empty
*/
public fun <T : Screen> fromList(frames: List<T>): BackStackScreen<T> {
require(frames.isNotEmpty()) {
"A BackStackScreen must have at least one frame."
}
return BackStackScreen(frames)
}

/**
* Builds a [BackStackScreen] from a list of [frames], or returns `null`
* if [frames] is empty.
*/
public fun <T : Screen> fromListOrNull(frames: List<T>): BackStackScreen<T>? {
return when {
frames.isEmpty() -> null
else -> BackStackScreen(frames)
}
}
}
}

@WorkflowUiExperimentalApi
public fun <T : Screen> List<T>.toBackStackScreenOrNull(): BackStackScreen<T>? = when {
isEmpty() -> null
else -> toBackStackScreen()
}
public fun <T : Screen> List<T>.toBackStackScreenOrNull(): BackStackScreen<T>? =
fromListOrNull(this)

@WorkflowUiExperimentalApi
public fun <T : Screen> List<T>.toBackStackScreen(): BackStackScreen<T> {
require(isNotEmpty())
return BackStackScreen(first(), subList(1, size))
}
public fun <T : Screen> List<T>.toBackStackScreen(): BackStackScreen<T> =
Companion.fromList(this)
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,8 @@ internal class BackStackScreenTest {

@Test fun `bottom and rest`() {
assertThat(
BackStackScreen(
bottom = S(1),
rest = listOf(S(2), S(3), S(4))
BackStackScreen.fromList(
listOf(element = S(1)) + listOf(S(2), S(3), S(4))
)
).isEqualTo(BackStackScreen(S(1), S(2), S(3), S(4)))
}
Expand Down
Loading