package com.suno.android.ui.screens.share_asset.components import android.icu.text.DateFormat import androidx.compose.animation.Crossfade import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.FilledIconButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.ProvideTextStyle import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect 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.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.media3.common.Player import com.suno.android.common_ui.R import com.suno.android.common_ui.components.menus.SelectorDropdownMenu import com.suno.android.common_ui.components.menus.SelectorDropdownMenuIconSide import com.suno.android.common_ui.theme.ExtendedTheme import com.suno.android.ui.screens.share_asset.ShareAssetEditorScreenState import kotlinx.collections.immutable.ImmutableList import kotlin.time.Duration @Composable internal fun VideoClipPreviewControls( player: Player, rangeStartTime: Duration, selectedDurationOption: ShareAssetEditorScreenState.RangeDurationOption, durationOptions: ImmutableList, onDurationOptionSelected: (ShareAssetEditorScreenState.RangeDurationOption) -> Unit, modifier: Modifier = Modifier, ) { var isMutedState by remember { mutableStateOf(player.volume == 0f) } DisposableEffect(player) { val listener = object : Player.Listener { override fun onVolumeChanged( volume: Float, ) { super.onVolumeChanged(volume) isMutedState = volume == 0f } } player.addListener(listener) onDispose { player.removeListener(listener) } } ProvideTextStyle( ExtendedTheme.typography.cardMeta.copy( fontFeatureSettings = "tnum", fontSize = 12.sp, fontWeight = FontWeight.Normal, ), ) { Row( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, modifier = modifier, ) { DurationSelector( selectedState = selectedDurationOption, options = durationOptions, onDurationOptionSelected = onDurationOptionSelected, ) WindowTimes( startTime = rangeStartTime, endTime = rangeStartTime + selectedDurationOption.duration, ) MuteButton( isMuted = isMutedState, onClick = { if (isMutedState) { player.volume = 1f } else { player.volume = 0f } }, ) } } } @Composable internal fun DurationSelector( selectedState: ShareAssetEditorScreenState.RangeDurationOption, options: ImmutableList, onDurationOptionSelected: (ShareAssetEditorScreenState.RangeDurationOption) -> Unit, modifier: Modifier = Modifier, ) { SelectorDropdownMenu( selectedItem = selectedState, textStyle = LocalTextStyle.current, color = ExtendedTheme.colors.backgroundSecondary, options = options, iconSize = DpSize(12.dp, 12.dp), iconSide = SelectorDropdownMenuIconSide.End, title = { this.name() }, modifier = modifier.sizeIn( minWidth = 58.dp, minHeight = 30.dp, ), ) { item, dismiss -> DropdownMenuItem( text = { Text( text = item.name(), textAlign = TextAlign.Center, ) }, onClick = { onDurationOptionSelected(item) dismiss() }, ) } } @Composable internal fun ShareAssetEditorScreenState.RangeDurationOption.name(): String = stringResource( id = com.suno.android.common_res.R.string.format_seconds_short, this.duration.inWholeSeconds, ) @Composable private fun WindowTimes( startTime: Duration, endTime: Duration, modifier: Modifier = Modifier, ) { val formatter = remember { DateFormat.getInstanceForSkeleton(DateFormat.MINUTE_SECOND) } val startTimeFormatted = remember(startTime / 1000) { formatter.format(startTime.inWholeMilliseconds) } val endTimeFormatted = remember(endTime / 1000) { formatter.format(endTime.inWholeMilliseconds) } Text( text = "$startTimeFormatted • $endTimeFormatted", modifier = modifier, ) } @Composable private fun MuteButton( isMuted: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier, ) { FilledIconButton( onClick = onClick, shape = CircleShape, colors = IconButtonDefaults.filledIconButtonColors( containerColor = ExtendedTheme.colors.backgroundSecondary, ), modifier = modifier.size( width = 58.dp, height = 30.dp, ), ) { Crossfade(isMuted) { state -> if (state) { Icon( painter = painterResource(R.drawable.volume_off), contentDescription = stringResource(com.suno.android.common_res.R.string.mute), tint = ExtendedTheme.colors.textPrimary, modifier = Modifier.size(18.dp), ) } else { Icon( painter = painterResource(R.drawable.volume_on), contentDescription = stringResource(com.suno.android.common_res.R.string.unmute), tint = ExtendedTheme.colors.textPrimary, modifier = Modifier.size(18.dp), ) } } } }