Lately I've been tinkering with some more advanced usages of the Compose libraries, and was trying to implement a MediaPlayer composable to be used to manage player layout, events, playback state etc.
I've ran into some trouble when I realized that I need to limit this element's layout to a specific method, just like in LazyColumn where only the item or items methods actually provide a Composable context.
I set out to try and imitate what they are doing in the hope of finding a solution for this, but the more I dug in the source code the more complex the implementation revealed itself to be, and I couldn't really understand what was going on.
Is it possible to copy this behavior from LazyColumn?
This is what I have so far:
@Composable
fun MediaPlayer(
playerState: MediaPlayerState = rememberMediaPlayerState(),
content: MediaPlayerScope.() -> Unit
) {
with(MediaPlayerScopeInstance) {
this.playerState = playerState
content()
}
}
interface MediaPlayerScope {
var controller: MediaPlayerController
var playerState: MediaPlayerState
fun mediaItems(items: List<MediaItem>)
fun <T> mediaItems(original: List<T>, mapper: (T) -> MediaItem)
fun playerLayout(layout: @Composable () -> Unit)
}
internal object MediaPlayerScopeInstance : MediaPlayerScope {
override var controller: MediaPlayerController = DefaultController
override var playerState = MediaPlayerState()
override fun mediaItems(items: List<MediaItem>) {
playerState.mediaItems = items
}
override fun <T> mediaItems(original: List<T>, mapper: (T) -> MediaItem) {
playerState.mediaItems = original.map(mapper)
}
override fun playerLayout(layout: @Composable () -> Unit) {
// this method should somehow invoke the layout parameter
}
}
As for usage I want to achieve something like this:
MediaPlayer {
mediaItems(viewModel.songList) {
it.asMediaItem()
}
// the next statement should show an error as this is not a composable context
Box {
}
// the end goal is to render this lambda to the screen
playerLayout {
// this should work
Box {
}
}
}
As you can see this behavior is working as I want it to aside for rendering the layout, this is where I got stuck
Any help would be appreciated!