Last active
August 5, 2021 21:30
-
-
Save rjrjr/c52eb172ed1787dd6b703ad20fe1a121 to your computer and use it in GitHub Desktop.
Gatekeeper workflow pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* In our production code, this typealias is more interesting, | |
* something like AlertContainerScreen<PanelContainerScreen<R>> | |
*/ | |
typealias MetaRootRendering<R>: AlertContainerScreen<R> | |
data class ActivityAndRoot<R> ( | |
val activity: Activity, | |
val root: R | |
) | |
/** | |
* Receives our root UI and the current Activity as props. | |
* When rendered, can choose to | |
* - wrap the given root rendering with modals | |
* - replace it entirely | |
* - return `null` to indicate that it doesn't want to interfere | |
*/ | |
interface GatekeeperWorkflow: | |
Workflow<ActivityAndRoot<Any>, Nothing, MetaRootRendering<Any>?> | |
class MetaRootWorkflow<R>( | |
private val realRootWorkflow: Workflow<R>, | |
val systemPermissionWorkflow: GatekeeperWorkflow, | |
val oneTrustWorkflow: GatekeeperWorkflow | |
): StatelessWorkflow<Activity, Nothing, MetaRootRendering<R>> { | |
/** In priority order. Dagger injected in real life. */ | |
private val gatekeepers = listOf( | |
systemPermissionWorkflow, oneTrustWorkflow | |
) | |
override fun render( | |
renderProps: Activity, | |
context: RenderContext | |
): RootRendering<GatekeeperScreen> { | |
// In this sketch we're always running the main UI, whether or | |
// not we show its rendering. | |
// | |
// You might instead want to prevent it from running until | |
// both Gatekeepers render null, or run some blocking | |
// Gatekeepers first and another set after. | |
val root = context.renderChild(realRootWorkflow) | |
// Note that we are careful always to render all gatekeepers, even if upstream | |
// ones are blocking downstream via non-null renderings. | |
val gateOrNull = gatekeepers | |
.mapNotNull { context.renderChild(it, ActivityAndRoot(renderProps, root) } | |
.firstOrNull() | |
return gateOrNull ?: AlertContainerScreen(root) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment