Skip to content

Yet another stab at a general wrapper / container interface #916

@rjrjr

Description

@rjrjr
import com.squareup.workflow1.ui.Screen

/**
 * A model type comprised of a set of other models of the same base type.
 *
 * @param C the invariant base type of the contents of such a container,
 * usually [Screen] or [Overlay]. It is common for the [Container] itself to
 * implement [C], but that is not a requirement. E.g., an [Overlay] might be 
 * container of [Screen].
 * @param T the specific subtype of [C] collected by this [Container].
 */
interface Container<C, T : C> {
  fun asSequence(): Sequence<T>

  /**
   * Returns a [Container] with the [transform]ed contents of the receiver.
   * It is expected that an implementation will take advantage of covariance
   * to declare its own type as the return type, rather than plain old [Container].
   * This requirement is not enforced because recursive generics are a fussy nuisance.
   */
  fun <U : C> mapContent(transform: (T) -> U): Container<C, U>
}

/**
 * A singleton [Container].
 */
interface Wrapper<C, T : C> : Container<C, T> {
  val content: T

  override fun asSequence(): Sequence<T> = sequenceOf(content)

  override fun <U : C> mapContent(transform: (T) -> U): Wrapper<C, U>
}

class WrappyScreen<S : Screen>(
  override val content: S
) : Screen, Wrapper<Screen, S> {
  override fun <U : Screen> mapContent(transform: (S) -> U): WrappyScreen<U> {
    return WrappyScreen(transform(content))
  }
}

class BStack<T : Screen>(
  val top: T,
  val backstack: List<T> = emptyList()
) : Container<Screen, T> {
  override fun asSequence(): Sequence<T> {
    return backstack.asSequence() + top
  }

  override fun <U : Screen> mapContent(transform: (T) -> U): BStack<U> {
    return BStack(transform(top), backstack.map(transform))
  }
}

Metadata

Metadata

Assignees

Labels

uiRelated to UI integration

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions