[fix] Landscape Playlist
This commit is contained in:
139
app/src/main/java/com/acitelight/aether/view/MiniPlaylistCard.kt
Normal file
139
app/src/main/java/com/acitelight/aether/view/MiniPlaylistCard.kt
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
package com.acitelight.aether.view
|
||||||
|
|
||||||
|
import android.R
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardColors
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.drawBehind
|
||||||
|
import androidx.compose.ui.draw.drawWithContent
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.PaintingStyle.Companion.Stroke
|
||||||
|
import androidx.compose.ui.graphics.drawOutline
|
||||||
|
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import coil3.ImageLoader
|
||||||
|
import coil3.compose.AsyncImage
|
||||||
|
import coil3.request.ImageRequest
|
||||||
|
import com.acitelight.aether.model.Video
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MiniPlaylistCard(modifier: Modifier, video: Video, imageLoader: ImageLoader, selected: Boolean, onClick: () -> Unit) {
|
||||||
|
val colorScheme = MaterialTheme.colorScheme
|
||||||
|
|
||||||
|
Card(
|
||||||
|
modifier = modifier
|
||||||
|
.height(80.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
colors = CardColors(
|
||||||
|
containerColor = Color.Transparent,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onSurface,
|
||||||
|
disabledContentColor = Color.Transparent,
|
||||||
|
disabledContainerColor = Color.Transparent
|
||||||
|
),
|
||||||
|
onClick = onClick
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Row()
|
||||||
|
{
|
||||||
|
AsyncImage(
|
||||||
|
model = ImageRequest.Builder(LocalContext.current)
|
||||||
|
.data(video.getCover())
|
||||||
|
.memoryCacheKey("${video.klass}/${video.id}/cover")
|
||||||
|
.diskCacheKey("${video.klass}/${video.id}/cover")
|
||||||
|
.listener(
|
||||||
|
onStart = { },
|
||||||
|
onError = { _, _ -> }
|
||||||
|
)
|
||||||
|
.build(),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.width(128.dp)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.then(
|
||||||
|
if (selected)
|
||||||
|
Modifier.drawWithContent {
|
||||||
|
drawContent()
|
||||||
|
|
||||||
|
val strokeWidth = 3.dp.toPx()
|
||||||
|
val shape = RoundedCornerShape(8.dp)
|
||||||
|
val outline = shape.createOutline(size, layoutDirection, this)
|
||||||
|
|
||||||
|
drawOutline(
|
||||||
|
outline = outline,
|
||||||
|
color = colorScheme.primary,
|
||||||
|
style = Stroke(width = strokeWidth)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Modifier
|
||||||
|
),
|
||||||
|
contentScale = ContentScale.Crop,
|
||||||
|
imageLoader = imageLoader
|
||||||
|
)
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 8.dp)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.CenterVertically),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Text(
|
||||||
|
modifier = Modifier,
|
||||||
|
text = video.video.name,
|
||||||
|
fontSize = 13.sp,
|
||||||
|
maxLines = 2,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
lineHeight = 14.sp,
|
||||||
|
color = if(selected) colorScheme.primary else colorScheme.onSurface
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier.weight(1f))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.height(16.dp),
|
||||||
|
text = video.klass,
|
||||||
|
fontSize = 8.sp,
|
||||||
|
lineHeight = 9.sp,
|
||||||
|
maxLines = 1,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = if(selected) colorScheme.primary else colorScheme.onSurface
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.height(16.dp),
|
||||||
|
text = formatTime(video.video.duration),
|
||||||
|
fontSize = 8.sp,
|
||||||
|
lineHeight = 9.sp,
|
||||||
|
maxLines = 1,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = if(selected) colorScheme.primary else colorScheme.onSurface
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -153,7 +153,6 @@ fun VideoPlayer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val colorScheme = MaterialTheme.colorScheme
|
|
||||||
videoPlayerViewModel.init(videoId)
|
videoPlayerViewModel.init(videoId)
|
||||||
|
|
||||||
activity.requestedOrientation =
|
activity.requestedOrientation =
|
||||||
@@ -164,39 +163,7 @@ fun VideoPlayer(
|
|||||||
|
|
||||||
if (videoPlayerViewModel.startPlaying) {
|
if (videoPlayerViewModel.startPlaying) {
|
||||||
if (videoPlayerViewModel.isLandscape) {
|
if (videoPlayerViewModel.isLandscape) {
|
||||||
Box {
|
|
||||||
VideoPlayerLandscape(videoPlayerViewModel)
|
VideoPlayerLandscape(videoPlayerViewModel)
|
||||||
AnimatedVisibility(
|
|
||||||
visible = videoPlayerViewModel.locked || videoPlayerViewModel.planeVisibility,
|
|
||||||
enter = fadeIn(
|
|
||||||
initialAlpha = 0f,
|
|
||||||
),
|
|
||||||
exit = fadeOut(
|
|
||||||
targetAlpha = 0f
|
|
||||||
),
|
|
||||||
modifier = Modifier.align(Alignment.CenterEnd)
|
|
||||||
) {
|
|
||||||
Card(
|
|
||||||
modifier = Modifier.padding(4.dp),
|
|
||||||
colors = CardDefaults.cardColors(
|
|
||||||
containerColor = colorScheme.primary.copy(
|
|
||||||
if (videoPlayerViewModel.locked) 0.2f else 1f
|
|
||||||
)
|
|
||||||
),
|
|
||||||
onClick = {
|
|
||||||
videoPlayerViewModel.locked = !videoPlayerViewModel.locked
|
|
||||||
}) {
|
|
||||||
Icon(
|
|
||||||
imageVector = if (videoPlayerViewModel.locked) Icons.Default.LockOpen else Icons.Default.Lock,
|
|
||||||
contentDescription = "Lock",
|
|
||||||
tint = Color.White.copy(if (videoPlayerViewModel.locked) 0.2f else 1f),
|
|
||||||
modifier = Modifier
|
|
||||||
.size(36.dp)
|
|
||||||
.padding(6.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
VideoPlayerPortal(videoPlayerViewModel, navController)
|
VideoPlayerPortal(videoPlayerViewModel, navController)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import androidx.activity.compose.BackHandler
|
|||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.slideInHorizontally
|
||||||
import androidx.compose.animation.slideInVertically
|
import androidx.compose.animation.slideInVertically
|
||||||
|
import androidx.compose.animation.slideOutHorizontally
|
||||||
import androidx.compose.animation.slideOutVertically
|
import androidx.compose.animation.slideOutVertically
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.gestures.detectDragGestures
|
import androidx.compose.foundation.gestures.detectDragGestures
|
||||||
@@ -16,28 +18,35 @@ import androidx.compose.foundation.gestures.detectTapGestures
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.List
|
||||||
import androidx.compose.material.icons.automirrored.filled.VolumeUp
|
import androidx.compose.material.icons.automirrored.filled.VolumeUp
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.ArrowBackIosNew
|
|
||||||
import androidx.compose.material.icons.filled.Brightness4
|
import androidx.compose.material.icons.filled.Brightness4
|
||||||
import androidx.compose.material.icons.filled.FastForward
|
import androidx.compose.material.icons.filled.FastForward
|
||||||
import androidx.compose.material.icons.filled.Fullscreen
|
|
||||||
import androidx.compose.material.icons.filled.FullscreenExit
|
import androidx.compose.material.icons.filled.FullscreenExit
|
||||||
|
import androidx.compose.material.icons.filled.Lock
|
||||||
|
import androidx.compose.material.icons.filled.LockOpen
|
||||||
import androidx.compose.material.icons.filled.Pause
|
import androidx.compose.material.icons.filled.Pause
|
||||||
import androidx.compose.material.icons.filled.PlayArrow
|
import androidx.compose.material.icons.filled.PlayArrow
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -54,20 +63,23 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.compose.ui.viewinterop.AndroidView
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.ui.PlayerView
|
import androidx.media3.ui.PlayerView
|
||||||
import com.acitelight.aether.ToggleFullScreen
|
import com.acitelight.aether.ToggleFullScreen
|
||||||
import com.acitelight.aether.viewModel.VideoPlayerViewModel
|
import com.acitelight.aether.viewModel.VideoPlayerViewModel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
|
||||||
@androidx.annotation.OptIn(UnstableApi::class)
|
@androidx.annotation.OptIn(UnstableApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
||||||
|
val colorScheme = MaterialTheme.colorScheme
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val activity = (context as? Activity)!!
|
val activity = (context as? Activity)!!
|
||||||
val exoPlayer: ExoPlayer = videoPlayerViewModel.player!!;
|
val exoPlayer: ExoPlayer = videoPlayerViewModel.player!!
|
||||||
|
|
||||||
val audioManager = remember { context.getSystemService(Context.AUDIO_SERVICE) as AudioManager }
|
val audioManager = remember { context.getSystemService(Context.AUDIO_SERVICE) as AudioManager }
|
||||||
val maxVolume = remember { audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) }
|
val maxVolume = remember { audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) }
|
||||||
@@ -78,6 +90,7 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val name by videoPlayerViewModel.currentName
|
val name by videoPlayerViewModel.currentName
|
||||||
|
val id by videoPlayerViewModel.currentId
|
||||||
|
|
||||||
fun setVolume(value: Int) {
|
fun setVolume(value: Int) {
|
||||||
audioManager.setStreamVolume(
|
audioManager.setStreamVolume(
|
||||||
@@ -100,25 +113,14 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
.align(Alignment.Center)
|
.align(Alignment.Center)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
AndroidView(
|
Box(
|
||||||
factory = {
|
Modifier
|
||||||
PlayerView(
|
.fillMaxSize()
|
||||||
it
|
.pointerInput(videoPlayerViewModel) {
|
||||||
).apply {
|
|
||||||
player = exoPlayer
|
|
||||||
useController = false
|
|
||||||
subtitleView?.let { sv ->
|
|
||||||
sv.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.pointerInput(Unit) {
|
|
||||||
detectDragGestures(
|
detectDragGestures(
|
||||||
onDragStart = { offset ->
|
onDragStart = { offset ->
|
||||||
if (videoPlayerViewModel.locked) return@detectDragGestures
|
if (videoPlayerViewModel.locked) return@detectDragGestures
|
||||||
if(offset.y > size.height * 0.9 || offset.y < size.height * 0.1)
|
if (offset.y > size.height * 0.9 || offset.y < size.height * 0.1)
|
||||||
videoPlayerViewModel.draggingPurpose = -3
|
videoPlayerViewModel.draggingPurpose = -3
|
||||||
// Set gesture protection for the bottom of the screen
|
// Set gesture protection for the bottom of the screen
|
||||||
// (Prevent conflicts with system gestures, such as dropdown status bar, bottom swipe up menu)
|
// (Prevent conflicts with system gestures, such as dropdown status bar, bottom swipe up menu)
|
||||||
@@ -157,9 +159,9 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
|
audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
|
||||||
.toFloat() / maxVolume.toFloat()
|
.toFloat() / maxVolume.toFloat()
|
||||||
if (dragAmount.y < 0)
|
if (dragAmount.y < 0)
|
||||||
setVolume(cu + 1);
|
setVolume(cu + 1)
|
||||||
else if (dragAmount.y > 0)
|
else if (dragAmount.y > 0)
|
||||||
setVolume(cu - 1);
|
setVolume(cu - 1)
|
||||||
} else if (videoPlayerViewModel.draggingPurpose == 1) {
|
} else if (videoPlayerViewModel.draggingPurpose == 1) {
|
||||||
moveBrit(dragAmount.y, activity, videoPlayerViewModel)
|
moveBrit(dragAmount.y, activity, videoPlayerViewModel)
|
||||||
}
|
}
|
||||||
@@ -167,7 +169,7 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.pointerInput(Unit) {
|
.pointerInput(videoPlayerViewModel) {
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onDoubleTap = {
|
onDoubleTap = {
|
||||||
if (videoPlayerViewModel.locked) return@detectTapGestures
|
if (videoPlayerViewModel.locked) return@detectTapGestures
|
||||||
@@ -177,6 +179,10 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
},
|
},
|
||||||
onTap = {
|
onTap = {
|
||||||
if (videoPlayerViewModel.locked) return@detectTapGestures
|
if (videoPlayerViewModel.locked) return@detectTapGestures
|
||||||
|
if (videoPlayerViewModel.showPlaylist) {
|
||||||
|
videoPlayerViewModel.showPlaylist = false
|
||||||
|
return@detectTapGestures
|
||||||
|
}
|
||||||
|
|
||||||
videoPlayerViewModel.planeVisibility =
|
videoPlayerViewModel.planeVisibility =
|
||||||
!videoPlayerViewModel.planeVisibility
|
!videoPlayerViewModel.planeVisibility
|
||||||
@@ -197,8 +203,23 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
}) {
|
||||||
|
AndroidView(
|
||||||
|
factory = {
|
||||||
|
PlayerView(
|
||||||
|
it
|
||||||
|
).apply {
|
||||||
|
player = exoPlayer
|
||||||
|
useController = false
|
||||||
|
subtitleView?.let { sv ->
|
||||||
|
sv.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
androidx.compose.animation.AnimatedVisibility(
|
androidx.compose.animation.AnimatedVisibility(
|
||||||
visible = videoPlayerViewModel.draggingPurpose == 0,
|
visible = videoPlayerViewModel.draggingPurpose == 0,
|
||||||
@@ -213,9 +234,7 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
{
|
{
|
||||||
Text(
|
Text(
|
||||||
text = "${formatTime((exoPlayer.duration * videoPlayerViewModel.playProcess).toLong())}/${
|
text = "${formatTime((exoPlayer.duration * videoPlayerViewModel.playProcess).toLong())}/${
|
||||||
formatTime(
|
formatTime(exoPlayer.duration)
|
||||||
(exoPlayer.duration).toLong()
|
|
||||||
)
|
|
||||||
}",
|
}",
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
modifier = Modifier.padding(bottom = 12.dp),
|
modifier = Modifier.padding(bottom = 12.dp),
|
||||||
@@ -234,9 +253,11 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
modifier = Modifier.align(Alignment.Center)
|
modifier = Modifier.align(Alignment.Center)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Row(Modifier
|
Row(
|
||||||
|
Modifier
|
||||||
.background(Color(0x88000000), RoundedCornerShape(18))
|
.background(Color(0x88000000), RoundedCornerShape(18))
|
||||||
.width(200.dp))
|
.width(200.dp)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.AutoMirrored.Filled.VolumeUp,
|
imageVector = Icons.AutoMirrored.Filled.VolumeUp,
|
||||||
@@ -269,9 +290,11 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
modifier = Modifier.align(Alignment.Center)
|
modifier = Modifier.align(Alignment.Center)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Row(Modifier
|
Row(
|
||||||
|
Modifier
|
||||||
.background(Color(0x88000000), RoundedCornerShape(18))
|
.background(Color(0x88000000), RoundedCornerShape(18))
|
||||||
.width(200.dp))
|
.width(200.dp)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.Brightness4,
|
imageVector = Icons.Default.Brightness4,
|
||||||
@@ -375,7 +398,8 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
Text(
|
Text(
|
||||||
text = name,
|
text = name,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
modifier = Modifier.padding(top = 12.dp)
|
modifier = Modifier
|
||||||
|
.padding(top = 12.dp)
|
||||||
.align(Alignment.CenterVertically),
|
.align(Alignment.CenterVertically),
|
||||||
fontSize = 18.sp
|
fontSize = 18.sp
|
||||||
)
|
)
|
||||||
@@ -407,9 +431,7 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "${formatTime((exoPlayer.duration * videoPlayerViewModel.playProcess).toLong())}/${
|
text = "${formatTime((exoPlayer.duration * videoPlayerViewModel.playProcess).toLong())}/${
|
||||||
formatTime(
|
formatTime(exoPlayer.duration)
|
||||||
(exoPlayer.duration).toLong()
|
|
||||||
)
|
|
||||||
}",
|
}",
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
modifier = Modifier.padding(bottom = 12.dp),
|
modifier = Modifier.padding(bottom = 12.dp),
|
||||||
@@ -464,6 +486,87 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
|||||||
modifier = Modifier.size(32.dp)
|
modifier = Modifier.size(32.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
videoPlayerViewModel.showPlaylist = true
|
||||||
|
},
|
||||||
|
Modifier
|
||||||
|
.size(36.dp)
|
||||||
|
.align(Alignment.CenterVertically)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
Icons.AutoMirrored.Filled.List,
|
||||||
|
contentDescription = "Playlist",
|
||||||
|
tint = Color.White,
|
||||||
|
modifier = Modifier.size(32.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = videoPlayerViewModel.locked || videoPlayerViewModel.planeVisibility,
|
||||||
|
enter = fadeIn(
|
||||||
|
initialAlpha = 0f,
|
||||||
|
),
|
||||||
|
exit = fadeOut(
|
||||||
|
targetAlpha = 0f
|
||||||
|
),
|
||||||
|
modifier = Modifier.align(Alignment.CenterEnd)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Card(
|
||||||
|
modifier = Modifier.padding(4.dp),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = colorScheme.primary.copy(
|
||||||
|
if (videoPlayerViewModel.locked) 0.2f else 1f
|
||||||
|
)
|
||||||
|
),
|
||||||
|
onClick = {
|
||||||
|
videoPlayerViewModel.locked = !videoPlayerViewModel.locked
|
||||||
|
}) {
|
||||||
|
Icon(
|
||||||
|
imageVector = if (videoPlayerViewModel.locked) Icons.Default.LockOpen else Icons.Default.Lock,
|
||||||
|
contentDescription = "Lock",
|
||||||
|
tint = Color.White.copy(if (videoPlayerViewModel.locked) 0.2f else 1f),
|
||||||
|
modifier = Modifier
|
||||||
|
.size(36.dp)
|
||||||
|
.padding(6.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = videoPlayerViewModel.showPlaylist,
|
||||||
|
enter = slideInHorizontally(initialOffsetX = { full -> full }),
|
||||||
|
exit = slideOutHorizontally(targetOffsetX = { full -> full }),
|
||||||
|
modifier = Modifier.align(Alignment.CenterEnd)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Card(
|
||||||
|
Modifier
|
||||||
|
.fillMaxHeight()
|
||||||
|
.width(320.dp)
|
||||||
|
.align(Alignment.CenterEnd),
|
||||||
|
shape = RoundedCornerShape(8.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = colorScheme.surface.copy(0.75f))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LazyColumn(contentPadding = PaddingValues(vertical = 4.dp)) {
|
||||||
|
items(videoPlayerViewModel.videos) { item ->
|
||||||
|
MiniPlaylistCard(Modifier.padding(4.dp), video = item, imageLoader = videoPlayerViewModel.imageLoader!!,
|
||||||
|
selected = id == item.id)
|
||||||
|
{
|
||||||
|
if (name == item.video.name)
|
||||||
|
return@MiniPlaylistCard
|
||||||
|
|
||||||
|
videoPlayerViewModel.viewModelScope.launch {
|
||||||
|
videoPlayerViewModel.startPlay(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class VideoPlayerViewModel @Inject constructor(
|
|||||||
val recentManager: RecentManager,
|
val recentManager: RecentManager,
|
||||||
val videoLibrary: VideoLibrary,
|
val videoLibrary: VideoLibrary,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
var showPlaylist by mutableStateOf(false)
|
||||||
var isLandscape by mutableStateOf(false)
|
var isLandscape by mutableStateOf(false)
|
||||||
var tabIndex by mutableIntStateOf(0)
|
var tabIndex by mutableIntStateOf(0)
|
||||||
var isPlaying by mutableStateOf(true)
|
var isPlaying by mutableStateOf(true)
|
||||||
|
|||||||
Reference in New Issue
Block a user