package com.suno.android.ui.screens.home.mediaplayer import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.suno.android.common_ui.components.bottom_bar.BottomMediaPlayerCard import com.suno.android.ui.screens.home.workspaces.WorkspacesBottomMediaPlayer private val LocalBottomPlayerHeight = compositionLocalOf { 0.dp } val WindowInsets.Companion.omniPlayer: WindowInsets @Composable get() { return WindowInsets( bottom = LocalBottomPlayerHeight.current, ) } @Composable fun HomeBottomMediaPlayerLayout( onCardSurfaceClick: () -> Unit, modifier: Modifier = Modifier, windowInsets: WindowInsets = WindowInsets.Companion.safeDrawing, isExpandedPlayer: Boolean = false, onOverflowClicked: (() -> Unit)? = null, onRemixClicked: (() -> Unit)? = null, hideMediaPlayer: Boolean = false, content: @Composable () -> Unit, ) { val density = LocalDensity.current var bottomPlayerHeight by remember { mutableStateOf(0.dp) } CompositionLocalProvider( LocalBottomPlayerHeight provides bottomPlayerHeight, ) { Box(modifier = modifier) { content() if (!hideMediaPlayer) { val bottomPlayerModifier = Modifier .align(Alignment.BottomCenter) .windowInsetsPadding( windowInsets.only(WindowInsetsSides.Bottom + WindowInsetsSides.Horizontal), ) .padding(horizontal = 2.dp) .onSizeChanged { // because this implementation relies on a state to update and trigger a recomposition // there is always at least a 1 frame delay when passing the new size to children bottomPlayerHeight = with(density) { it.height.toDp() } } if (isExpandedPlayer) { WorkspacesBottomMediaPlayer( modifier = bottomPlayerModifier, onCardSurfaceClick = { onCardSurfaceClick.invoke() }, onOverflowMenuClicked = { onOverflowClicked?.invoke() }, onRemixClicked = { onRemixClicked?.invoke() }, ) } else { HomeBottomMediaPlayer( onCardSurfaceClick = onCardSurfaceClick, modifier = bottomPlayerModifier, ) } } } } } @Composable fun HomeBottomMediaPlayer( modifier: Modifier = Modifier, viewModel: HomeBottomMediaPlayerViewModel = hiltViewModel(), onCardSurfaceClick: () -> Unit, ) { val viewState by viewModel.viewState.collectAsStateWithLifecycle() if (viewState.startedPlayingMusic) { BottomMediaPlayerCard( modifier = modifier.fillMaxWidth(), isPlaying = viewState.isPlaying, titleText = viewState.nowPlayingClip?.nowPlayingTitle, clipImageUrl = viewState.nowPlayingClip?.albumImageUrl, artistName = viewState.nowPlayingClip?.artistName, onPlayPauseClick = { viewModel.onPlayPauseClicked() }, onNextClick = { viewModel.onNextClicked() }, onCardSurfaceClick = { onCardSurfaceClick() }, clipProgress = viewState.currentTimestamp, clipLength = viewState.nowPlayingClip?.duration, ) } }