package com.example.ui.components import android.net.Uri import androidx.annotation.OptIn import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MusicNote import androidx.compose.material.icons.filled.Pause import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.SkipNext import androidx.compose.material.icons.filled.Videocam import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.media3.common.util.UnstableApi import coil.compose.AsyncImage import com.example.data.model.MediaItemData import com.example.playback.PlaybackManager import com.example.ui.theme.AccentViolet import com.example.ui.theme.DividerSubtle import com.example.ui.theme.SurfaceElevated import com.example.ui.theme.TextPrimary import com.example.ui.theme.TextSecondary @OptIn(UnstableApi::class) @Composable fun MiniPlayerBar( mediaItem: MediaItemData, onClick: () -> Unit, modifier: Modifier = Modifier ) { val isPlaying by PlaybackManager.isPlaying.collectAsState() val positionMs by PlaybackManager.currentPositionMs.collectAsState() val durationMs by PlaybackManager.durationMs.collectAsState() val progress = if (durationMs > 0) (positionMs.toFloat() / durationMs.toFloat()).coerceIn(0f, 1f) else 0f Surface( modifier = modifier .fillMaxWidth() .padding(horizontal = 12.dp, vertical = 6.dp) .clip(RoundedCornerShape(14.dp)) .clickable { onClick() } .testTag("mini_player_bar"), color = SurfaceElevated, shadowElevation = 8.dp ) { Column { LinearProgressIndicator( progress = { progress }, modifier = Modifier .fillMaxWidth() .height(2.dp), color = AccentViolet, trackColor = DividerSubtle ) Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 12.dp, vertical = 8.dp), verticalAlignment = Alignment.CenterVertically ) { // Thumbnail Box( modifier = Modifier .size(44.dp) .clip(RoundedCornerShape(8.dp)) .background(DividerSubtle), contentAlignment = Alignment.Center ) { if (!mediaItem.albumArtUri.isNullOrBlank()) { AsyncImage( model = Uri.parse(mediaItem.albumArtUri), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier.fillMaxSize() ) } else { Icon( imageVector = if (mediaItem.isVideo) Icons.Default.Videocam else Icons.Default.MusicNote, contentDescription = null, tint = AccentViolet, modifier = Modifier.size(24.dp) ) } } Spacer(modifier = Modifier.width(12.dp)) // Title & Artist Column(modifier = Modifier.weight(1f)) { Text( text = mediaItem.title, color = TextPrimary, fontSize = 14.sp, fontWeight = FontWeight.SemiBold, maxLines = 1, overflow = TextOverflow.Ellipsis ) Text( text = if (mediaItem.isVideo) "Video • ${mediaItem.formattedDuration}" else "${mediaItem.artist} • ${mediaItem.formattedDuration}", color = TextSecondary, fontSize = 12.sp, maxLines = 1, overflow = TextOverflow.Ellipsis ) } // Play/Pause IconButton( onClick = { PlaybackManager.togglePlayPause() }, modifier = Modifier.testTag("mini_player_play_pause") ) { Icon( imageVector = if (isPlaying) Icons.Default.Pause else Icons.Default.PlayArrow, contentDescription = if (isPlaying) "Pause" else "Play", tint = AccentViolet, modifier = Modifier.size(28.dp) ) } // Next IconButton( onClick = { PlaybackManager.playNext() }, modifier = Modifier.testTag("mini_player_next") ) { Icon( imageVector = Icons.Default.SkipNext, contentDescription = "Next", tint = TextPrimary, modifier = Modifier.size(24.dp) ) } } } } }