mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2026-09-24 18:01:51 +00:00
Extract thumbnail into common composable
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package org.schabi.newpipe.ui.components.items.common
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Icon
|
||||
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.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil3.compose.AsyncImage
|
||||
import org.schabi.newpipe.extractor.Image
|
||||
import org.schabi.newpipe.util.image.ImageStrategy
|
||||
|
||||
@Composable
|
||||
fun Thumbnail(
|
||||
images: List<Image>,
|
||||
imageDescription: String,
|
||||
@DrawableRes imagePlaceholder: Int,
|
||||
cornerBackgroundColor: Color,
|
||||
cornerIcon: ImageVector?,
|
||||
cornerText: String,
|
||||
contentScale: ContentScale,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Box(contentAlignment = Alignment.BottomEnd) {
|
||||
AsyncImage(
|
||||
model = ImageStrategy.choosePreferredImage(images),
|
||||
contentDescription = imageDescription,
|
||||
placeholder = painterResource(imagePlaceholder),
|
||||
error = painterResource(imagePlaceholder),
|
||||
contentScale = contentScale,
|
||||
modifier = modifier
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(2.dp)
|
||||
.background(cornerBackgroundColor)
|
||||
.padding(2.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
if (cornerIcon != null) {
|
||||
Icon(
|
||||
imageVector = cornerIcon,
|
||||
contentDescription = null,
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = cornerText,
|
||||
color = Color.White,
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-46
@@ -1,28 +1,17 @@
|
||||
package org.schabi.newpipe.ui.components.items.playlist
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.PlaylistPlay
|
||||
import androidx.compose.material3.Icon
|
||||
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.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil3.compose.AsyncImage
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.ui.components.items.Playlist
|
||||
import org.schabi.newpipe.ui.components.items.common.Thumbnail
|
||||
import org.schabi.newpipe.util.Localization
|
||||
import org.schabi.newpipe.util.image.ImageStrategy
|
||||
|
||||
@Composable
|
||||
fun PlaylistThumbnail(
|
||||
@@ -30,37 +19,14 @@ fun PlaylistThumbnail(
|
||||
modifier: Modifier = Modifier,
|
||||
contentScale: ContentScale = ContentScale.Fit
|
||||
) {
|
||||
Box(contentAlignment = Alignment.BottomEnd) {
|
||||
AsyncImage(
|
||||
model = ImageStrategy.choosePreferredImage(playlist.thumbnails),
|
||||
contentDescription = null,
|
||||
placeholder = painterResource(R.drawable.placeholder_thumbnail_playlist),
|
||||
error = painterResource(R.drawable.placeholder_thumbnail_playlist),
|
||||
contentScale = contentScale,
|
||||
modifier = modifier
|
||||
)
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(2.dp)
|
||||
.background(Color.Black.copy(alpha = 0.5f))
|
||||
.padding(2.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Default.PlaylistPlay,
|
||||
contentDescription = null,
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
|
||||
val context = LocalContext.current
|
||||
Text(
|
||||
text = Localization.localizeStreamCountMini(context, playlist.streamCount),
|
||||
color = Color.White,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
modifier = Modifier.padding(start = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
Thumbnail(
|
||||
images = playlist.thumbnails,
|
||||
imageDescription = stringResource(R.string.playlist_content_description, playlist.name),
|
||||
imagePlaceholder = R.drawable.placeholder_thumbnail_playlist,
|
||||
cornerBackgroundColor = Color.Black.copy(alpha = 0.5f),
|
||||
cornerIcon = Icons.AutoMirrored.Default.PlaylistPlay,
|
||||
cornerText = Localization.localizeStreamCountMini(LocalContext.current, playlist.streamCount),
|
||||
contentScale = contentScale,
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
|
||||
+16
-34
@@ -1,33 +1,25 @@
|
||||
package org.schabi.newpipe.ui.components.items.stream
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableLongStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil3.compose.AsyncImage
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.ui.components.items.Stream
|
||||
import org.schabi.newpipe.ui.components.items.common.Thumbnail
|
||||
import org.schabi.newpipe.util.Localization
|
||||
import org.schabi.newpipe.util.StreamTypeUtil
|
||||
import org.schabi.newpipe.util.image.ImageStrategy
|
||||
import org.schabi.newpipe.viewmodels.StreamViewModel
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
@@ -40,31 +32,21 @@ fun StreamThumbnail(
|
||||
contentScale: ContentScale = ContentScale.Fit
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
Box(contentAlignment = Alignment.BottomEnd) {
|
||||
AsyncImage(
|
||||
model = ImageStrategy.choosePreferredImage(stream.thumbnails),
|
||||
contentDescription = null,
|
||||
placeholder = painterResource(R.drawable.placeholder_thumbnail_video),
|
||||
error = painterResource(R.drawable.placeholder_thumbnail_video),
|
||||
contentScale = contentScale,
|
||||
modifier = modifier
|
||||
)
|
||||
|
||||
val isLive = StreamTypeUtil.isLiveStream(stream.type)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(2.dp)
|
||||
.background(if (isLive) Color.Red else Color.Black.copy(alpha = 0.5f))
|
||||
.padding(2.dp),
|
||||
text = if (isLive) {
|
||||
stringResource(R.string.duration_live)
|
||||
} else {
|
||||
Localization.getDurationString(stream.duration)
|
||||
},
|
||||
color = Color.White,
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
}
|
||||
val isLive = StreamTypeUtil.isLiveStream(stream.type)
|
||||
Thumbnail(
|
||||
images = stream.thumbnails,
|
||||
imageDescription = stringResource(R.string.stream_content_description, stream.name),
|
||||
imagePlaceholder = R.drawable.placeholder_thumbnail_video,
|
||||
cornerBackgroundColor = if (isLive) Color.Red else Color.Black.copy(alpha = 0.5f),
|
||||
cornerIcon = null,
|
||||
cornerText = if (isLive) {
|
||||
stringResource(R.string.duration_live)
|
||||
} else {
|
||||
Localization.getDurationString(stream.duration)
|
||||
},
|
||||
contentScale = contentScale,
|
||||
modifier = modifier
|
||||
)
|
||||
|
||||
if (showProgress) {
|
||||
val streamViewModel = viewModel<StreamViewModel>()
|
||||
|
||||
@@ -861,6 +861,8 @@
|
||||
<string name="newpipe_extractor_description">NewPipeExtractor is a library for extracting things from streaming sites. It is a core component of NewPipe, but could be used independently.</string>
|
||||
<string name="history_sort_label">Sort by</string>
|
||||
<string name="clear_history_description">Button to clear watch history</string>
|
||||
<string name="playlist_content_description">Thumbnail for playlist %1$s</string>
|
||||
<string name="stream_content_description">Thumbnail for stream %1$s</string>
|
||||
<plurals name="comments">
|
||||
<item quantity="one">%d comment</item>
|
||||
<item quantity="other">%d comments</item>
|
||||
|
||||
Reference in New Issue
Block a user