Extract thumbnail into common composable

This commit is contained in:
Isira Seneviratne
2025-01-27 07:36:48 +05:30
parent 21caa6ce13
commit 5abc03c4cf
4 changed files with 100 additions and 80 deletions
@@ -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
)
}
}
}
@@ -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
)
}
@@ -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>()
+2
View File
@@ -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>