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

1/4 fun ComponentDialog.setContent() replaces ScreenOverlayDialogFactory #1026

Merged
merged 4 commits into from
Jun 26, 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
@@ -1,42 +1,39 @@
package com.squareup.sample.container.panel

import android.app.Dialog
import android.content.Context
import android.graphics.Rect
import androidx.appcompat.app.AppCompatDialog
import com.squareup.sample.container.R
import com.squareup.workflow1.ui.Screen
import com.squareup.workflow1.ui.ScreenViewHolder
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.container.OverlayDialogFactory
import com.squareup.workflow1.ui.container.OverlayDialogHolder
import com.squareup.workflow1.ui.container.ScreenOverlayDialogFactory
import com.squareup.workflow1.ui.container.asDialogHolderWithContent
import com.squareup.workflow1.ui.container.setBounds
import com.squareup.workflow1.ui.container.setContent
import com.squareup.workflow1.ui.show
import kotlin.reflect.KClass

/**
* Android support for [PanelOverlay].
*/
@OptIn(WorkflowUiExperimentalApi::class)
internal object PanelOverlayDialogFactory :
ScreenOverlayDialogFactory<Screen, PanelOverlay<Screen>>(
type = PanelOverlay::class
) {
/**
* Forks the default implementation to apply [R.style.PanelDialog] for
* enter and exit animation, and to customize [bounds][OverlayDialogHolder.onUpdateBounds].
*/
override fun buildDialogWithContent(
internal object PanelOverlayDialogFactory : OverlayDialogFactory<PanelOverlay<Screen>> {
override val type: KClass<in PanelOverlay<Screen>> = PanelOverlay::class

override fun buildDialog(
initialRendering: PanelOverlay<Screen>,
initialEnvironment: ViewEnvironment,
content: ScreenViewHolder<Screen>
context: Context
): OverlayDialogHolder<PanelOverlay<Screen>> {
val dialog = Dialog(content.view.context, R.style.PanelDialog)
dialog.setContent(content)
val dialog = AppCompatDialog(context, R.style.PanelDialog)

val realHolder = dialog.asDialogHolderWithContent(initialRendering, initialEnvironment)

return OverlayDialogHolder(
initialEnvironment = initialEnvironment,
dialog = dialog,
onUpdateBounds = { bounds ->
// We replace the default onUpdateBounds function with one that gives the
// panel a square shape on tablets. See OverlayDialogFactory for more details
// on the bounds mechanism.
return object : OverlayDialogHolder<PanelOverlay<Screen>> by realHolder {
override val onUpdateBounds: ((Rect) -> Unit) = { bounds ->
rjrjr marked this conversation as resolved.
Show resolved Hide resolved
val refinedBounds: Rect = if (!dialog.context.isTablet) {
// On a phone, fill the bounds entirely.
bounds
Expand All @@ -62,8 +59,6 @@ internal object PanelOverlayDialogFactory :

dialog.setBounds(refinedBounds)
}
) { overlayRendering, environment ->
content.show(overlayRendering.content, environment)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ class HelloBackButtonEspressoTest {
.around(IdlingDispatcherRule)

@Test fun wrappedTakesPrecedence() {
// The root workflow (AreYouSureWorkflow) wraps its child renderings
// (instances of HelloBackButtonScreen) in its own BackButtonScreen,
// which shows the "Are you sure" dialog.
// That should only be in effect on the Able screen, which sets no backHandler of its
// own. The Baker and Charlie screens set their own backHandlers,
// which should take precedence over the root one. Thus, we should
// be able to push to Charlie and pop all the way back to Able
// without seeing the "Are you sure" dialog.
onView(withId(R.id.hello_message)).apply {
check(matches(withText("Able")))
perform(click())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ object AreYouSureWorkflow :
BackButtonScreen(ableBakerCharlie) {
// While we always provide a back button handler, by default the view code
// associated with BackButtonScreen ignores ours if the view created for the
// wrapped rendering sets a handler of its own. (Set BackButtonScreen.override
// wrapped rendering sets a handler of its own. (Set BackButtonScreen.shadow
// to change this precedence.)
context.actionSink.send(maybeQuit)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.squareup.sample.hellobackbutton.databinding.HelloBackButtonLayoutBind
import com.squareup.workflow1.ui.AndroidScreen
import com.squareup.workflow1.ui.ScreenViewFactory
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.backPressedHandler
import com.squareup.workflow1.ui.setBackHandler

@OptIn(WorkflowUiExperimentalApi::class)
data class HelloBackButtonScreen(
Expand All @@ -18,6 +18,6 @@ data class HelloBackButtonScreen(
ScreenViewFactory.fromViewBinding(HelloBackButtonLayoutBinding::inflate) { rendering, _ ->
helloMessage.text = rendering.message
helloMessage.setOnClickListener { rendering.onClick() }
helloMessage.backPressedHandler = rendering.onBackPressed
helloMessage.setBackHandler(rendering.onBackPressed)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.squareup.sample.poetry

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
Expand All @@ -15,9 +16,9 @@ import com.squareup.workflow1.ui.ScreenViewFactory
import com.squareup.workflow1.ui.ScreenViewRunner
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.backPressedHandler
import com.squareup.workflow1.ui.container.BackStackConfig
import com.squareup.workflow1.ui.container.BackStackConfig.Other
import com.squareup.workflow1.ui.setBackHandler

@OptIn(WorkflowUiExperimentalApi::class)
data class StanzaListScreen(
Expand All @@ -40,6 +41,7 @@ private class StanzaListLayoutRunner(view: View) : ScreenViewRunner<StanzaListSc

private val adapter = Adapter()

@SuppressLint("NotifyDataSetChanged")
override fun showRendering(
rendering: StanzaListScreen,
environment: ViewEnvironment
Expand All @@ -53,10 +55,10 @@ private class StanzaListLayoutRunner(view: View) : ScreenViewRunner<StanzaListSc

if (environment[BackStackConfig] == Other) {
toolbar.setNavigationOnClickListener { rendering.onExit() }
toolbar.backPressedHandler = rendering.onExit
toolbar.setBackHandler(rendering.onExit)
} else {
toolbar.navigationIcon = null
toolbar.backPressedHandler = null
toolbar.setBackHandler {}
}

if (rendering.selection >= 0) recyclerView.scrollToPosition(rendering.selection)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import com.squareup.workflow1.ui.ScreenViewFactory
import com.squareup.workflow1.ui.ScreenViewRunner
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.backPressedHandler
import com.squareup.workflow1.ui.container.BackStackConfig
import com.squareup.workflow1.ui.container.BackStackConfig.None
import com.squareup.workflow1.ui.setBackHandler

@OptIn(WorkflowUiExperimentalApi::class)
data class StanzaScreen(
Expand Down Expand Up @@ -93,8 +93,10 @@ private class StanzaLayoutRunner(private val view: View) : ScreenViewRunner<Stan
toolbar.navigationIcon = null
}

view.backPressedHandler = rendering.onGoBack
val goBackOrUp = rendering.onGoBack
?: rendering.onGoUp.takeIf { environment[OverviewDetailConfig] != Detail }

view.setBackHandler(goBackOrUp)
}

private fun TextView.setTabulatedText(lines: List<String>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import com.squareup.workflow1.ui.ScreenViewRunner
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.WorkflowViewStub
import com.squareup.workflow1.ui.backPressedHandler
import com.squareup.workflow1.ui.setBackHandler
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.ExperimentalTime
Expand Down Expand Up @@ -44,7 +44,7 @@ class ShakeableTimeMachineLayoutRunner(
environment: ViewEnvironment
) {
// Only handle back presses explicitly if in playback mode.
view.backPressedHandler = rendering.onResumeRecording.takeUnless { rendering.recording }
view.setBackHandler(rendering.onResumeRecording.takeUnless { rendering.recording })

seek.max = rendering.totalDuration.toProgressInt()
seek.progress = rendering.playbackPosition.toProgressInt()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.squareup.sample.tictactoe.databinding.LoginLayoutBinding
import com.squareup.workflow1.ui.ScreenViewFactory
import com.squareup.workflow1.ui.ScreenViewFactory.Companion.fromViewBinding
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.backPressedHandler
import com.squareup.workflow1.ui.setBackHandler

@OptIn(WorkflowUiExperimentalApi::class)
internal val LoginViewFactory: ScreenViewFactory<LoginScreen> =
Expand All @@ -15,5 +15,5 @@ internal val LoginViewFactory: ScreenViewFactory<LoginScreen> =
rendering.onLogin(loginEmail.text.toString(), loginPassword.text.toString())
}

root.backPressedHandler = { rendering.onCancel() }
root.setBackHandler(rendering.onCancel)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import com.squareup.sample.tictactoe.databinding.SecondFactorLayoutBinding
import com.squareup.workflow1.ui.ScreenViewFactory
import com.squareup.workflow1.ui.ScreenViewFactory.Companion.fromViewBinding
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.backPressedHandler
import com.squareup.workflow1.ui.setBackHandler

@OptIn(WorkflowUiExperimentalApi::class)
internal val SecondFactorViewFactory: ScreenViewFactory<SecondFactorScreen> =
fromViewBinding(SecondFactorLayoutBinding::inflate) { rendering, _ ->
root.backPressedHandler = { rendering.onCancel() }
root.setBackHandler(rendering.onCancel)
secondFactorToolbar.setNavigationOnClickListener { rendering.onCancel() }

secondFactorErrorMessage.text = rendering.errorMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.squareup.workflow1.ui.ScreenViewFactory.Companion.fromViewBinding
import com.squareup.workflow1.ui.ScreenViewRunner
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.backPressedHandler
import com.squareup.workflow1.ui.setBackHandler

@OptIn(WorkflowUiExperimentalApi::class)
internal class GameOverLayoutRunner(
Expand All @@ -40,14 +40,15 @@ internal class GameOverLayoutRunner(
rendering.onPlayAgain()
true
}
binding.root.backPressedHandler = { rendering.onExit() }
binding.root.setBackHandler(rendering.onExit)

when (rendering.endGameState.syncState) {
SAVING -> {
saveItem.isEnabled = false
saveItem.title = "saving…"
saveItem.setOnMenuItemClickListener(null)
}

SAVE_FAILED -> {
saveItem.isEnabled = true
saveItem.title = "Unsaved"
Expand All @@ -56,6 +57,7 @@ internal class GameOverLayoutRunner(
true
}
}

SAVED -> {
saveItem.isVisible = false
saveItem.setOnMenuItemClickListener(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.squareup.sample.tictactoe.databinding.GamePlayLayoutBinding
import com.squareup.workflow1.ui.ScreenViewFactory
import com.squareup.workflow1.ui.ScreenViewFactory.Companion.fromViewBinding
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.backPressedHandler
import com.squareup.workflow1.ui.setBackHandler

@OptIn(WorkflowUiExperimentalApi::class)
internal val GamePlayViewFactory: ScreenViewFactory<GamePlayScreen> =
Expand All @@ -15,7 +15,7 @@ internal val GamePlayViewFactory: ScreenViewFactory<GamePlayScreen> =
rendering.gameState.board.render(gamePlayBoard.root)

setCellClickListeners(gamePlayBoard.root, rendering.gameState, rendering.onClick)
root.backPressedHandler = rendering.onQuit
root.setBackHandler(rendering.onQuit)
}

private fun setCellClickListeners(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.squareup.sample.tictactoe.databinding.NewGameLayoutBinding
import com.squareup.workflow1.ui.ScreenViewFactory
import com.squareup.workflow1.ui.ScreenViewFactory.Companion.fromViewBinding
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.backPressedHandler
import com.squareup.workflow1.ui.setBackHandler

@OptIn(WorkflowUiExperimentalApi::class)
internal val NewGameViewFactory: ScreenViewFactory<NewGameScreen> =
Expand All @@ -16,5 +16,5 @@ internal val NewGameViewFactory: ScreenViewFactory<NewGameScreen> =
rendering.onStartGame(playerX.text.toString(), playerO.text.toString())
}

root.backPressedHandler = { rendering.onCancel() }
root.setBackHandler(rendering.onCancel)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import com.squareup.workflow1.ui.ScreenViewFactory
import com.squareup.workflow1.ui.ScreenViewRunner
import com.squareup.workflow1.ui.ViewEnvironment
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
import com.squareup.workflow1.ui.backPressedHandler
import com.squareup.workflow1.ui.container.BackStackConfig
import com.squareup.workflow1.ui.container.BackStackConfig.Other
import com.squareup.workflow1.ui.control
import com.squareup.workflow1.ui.setBackHandler

@OptIn(WorkflowUiExperimentalApi::class)
data class TodoEditorScreen(
Expand Down Expand Up @@ -62,7 +62,7 @@ private class Runner(

if (environment[BackStackConfig] == Other) {
todoEditorToolbar.setNavigationOnClickListener { rendering.onGoBackClicked() }
root.backPressedHandler = { rendering.onGoBackClicked() }
root.setBackHandler(rendering.onGoBackClicked)
} else {
todoEditorToolbar.navigationIcon = null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
:workflow-ui:compose
:workflow-ui:core-android
:workflow-ui:core-common
androidx.activity:activity-compose:1.6.1
androidx.activity:activity-ktx:1.6.1
androidx.activity:activity:1.6.1
androidx.annotation:annotation-experimental:1.1.0
Expand Down
1 change: 1 addition & 0 deletions workflow-ui/compose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ dependencies {
api(project(":workflow-ui:core-common"))

implementation(composeBom)
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.compose.foundation.layout)
implementation(libs.androidx.compose.runtime.saveable)
implementation(libs.androidx.compose.ui)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
:workflow-runtime
:workflow-ui:core-android
:workflow-ui:core-common
androidx.activity:activity-compose:1.6.1
androidx.activity:activity-ktx:1.6.1
androidx.activity:activity:1.6.1
androidx.annotation:annotation-experimental:1.1.0
Expand Down
Loading