player-ui / player

https://player-ui.github.io
MIT License
71 stars 45 forks source link

Provide the bridge to Android Player for Jetpack Compose users #89

Open brocollie08 opened 1 year ago

brocollie08 commented 1 year ago

Give the consumers a way to render Android Player rendered UI as a @Composable so they are able to choose between rendering Composable Player assets and traditional Android view Player assets

We currently have working code for a composable Android ManagedPlayer (multi-flow experiences) as follows

@Composable
fun ManagedPlayer(
    plugins: List<Plugin>,
    flowManager: AsyncFlowIterator,
    onComplete: @Composable (CompletedState?) -> Unit,
    fallback: @Composable (Throwable) -> Unit,
    loading: @Composable () -> Unit = { CircularProgressIndicator() },
    modifier: Modifier = Modifier,
) {
    val viewModel = remember(plugins, flowManager) {
        object : PlayerViewModel(flowManager) {
            override val plugins = plugins
        }
    }
    LaunchedEffect(viewModel) {
        viewModel.start()
    }
    ManagedPlayer(viewModel, onComplete, fallback, loading, modifier)
}

@Composable
fun ManagedPlayer(
    playerViewModel: PlayerViewModel,
    onComplete: @Composable (CompletedState?) -> Unit,
    fallback: @Composable (ManagedPlayerErrorContext) -> Unit,
    loading: @Composable () -> Unit = { CircularProgressIndicator() },
    modifier: Modifier = Modifier,
) {
    Box(
        Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .background(brush = outsideOrbVerticalGradient)
            .then(modifier),
        propagateMinConstraints = true,
    ) {
        val state by playerViewModel.state.collectAsState()
        when (val currentState = state) {
            ManagedPlayerState.NotStarted -> loading()
            ManagedPlayerState.Pending -> loading()
            is ManagedPlayerState.Running -> currentState.asset?.compose()
            is ManagedPlayerState.Error -> fallback(ManagedPlayerErrorContext(currentState.exception, playerViewModel::retry, playerViewModel::start))
            is ManagedPlayerState.Done -> onComplete(currentState.completedState)
        }
    }
}

class ManagedPlayerErrorContext(
    val error: Throwable,
    val retry: () -> Unit,
    val reset: () -> Unit
)

This code has not been moved into this project, we would like to potentially patternize it and move it over, as well as creating a similar composable for a single flow experience by feeding in an AsyncFlowIterator with one flow

OleDakotaJoe commented 1 year ago

@brocollie08, I posted on issue #90, I'd like to get involved in this project. I see this is "good first issue". Does this issue need to be predecessor to #90 ?

brocollie08 commented 1 year ago

@OleDakotaJoe Thanks for your interest in contributing!

This one is not necessarily a pre-req for #90 but you won't be able to easily see the outcome of #90 without this.

I edited the original description with some more code, you can see in the case of ManagedPlayerState.Running, asset.compose() is called, that's where the connection is between these two issues, that's the entry point for the asset being rendered on the UI