1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2025-02-03 12:49:14 +00:00

Show dropdown menu on long click, make some adjustments

This commit is contained in:
Isira Seneviratne 2024-07-09 05:34:28 +05:30
parent 5e33b69316
commit bbdff4b093
6 changed files with 206 additions and 78 deletions

View File

@ -1,8 +1,10 @@
package org.schabi.newpipe.compose.stream package org.schabi.newpipe.compose.stream
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.clickable import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -20,39 +22,55 @@ import androidx.compose.ui.unit.dp
import org.schabi.newpipe.compose.theme.AppTheme import org.schabi.newpipe.compose.theme.AppTheme
import org.schabi.newpipe.extractor.stream.StreamInfoItem import org.schabi.newpipe.extractor.stream.StreamInfoItem
@OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun StreamCardItem(stream: StreamInfoItem, onClick: (StreamInfoItem) -> Unit) { fun StreamCardItem(
Column( stream: StreamInfoItem,
modifier = Modifier isSelected: Boolean = false,
.clickable(onClick = { onClick(stream) }) onClick: (StreamInfoItem) -> Unit = {},
.padding(top = 12.dp, start = 2.dp, end = 2.dp) onLongClick: (StreamInfoItem) -> Unit = {},
) { onDismissPopup: () -> Unit = {}
StreamThumbnail( ) {
stream = stream, Box {
modifier = Modifier.fillMaxWidth(), Column(
contentScale = ContentScale.FillWidth modifier = Modifier
) .combinedClickable(
onLongClick = { onLongClick(stream) },
Column(modifier = Modifier.padding(10.dp)) { onClick = { onClick(stream) }
Text( )
text = stream.name, .padding(top = 12.dp, start = 2.dp, end = 2.dp)
overflow = TextOverflow.Ellipsis, ) {
style = MaterialTheme.typography.titleSmall, StreamThumbnail(
maxLines = 2 modifier = Modifier.fillMaxWidth(),
stream = stream,
contentScale = ContentScale.FillWidth
) )
Row( Column(modifier = Modifier.padding(10.dp)) {
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(text = stream.uploaderName.orEmpty(), style = MaterialTheme.typography.bodySmall)
Text( Text(
text = getStreamInfoDetail(stream), text = stream.name,
style = MaterialTheme.typography.bodySmall overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleSmall,
maxLines = 2
) )
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(text = stream.uploaderName.orEmpty(), style = MaterialTheme.typography.bodySmall)
Text(
text = getStreamInfoDetail(stream),
style = MaterialTheme.typography.bodySmall
)
}
} }
} }
if (isSelected) {
StreamMenu(onDismissPopup)
}
} }
} }
@ -64,7 +82,7 @@ private fun StreamCardItemPreview(
) { ) {
AppTheme { AppTheme {
Surface(color = MaterialTheme.colorScheme.background) { Surface(color = MaterialTheme.colorScheme.background) {
StreamCardItem(stream) {} StreamCardItem(stream)
} }
} }
} }

View File

@ -1,7 +1,9 @@
package org.schabi.newpipe.compose.stream package org.schabi.newpipe.compose.stream
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.clickable import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
@ -17,28 +19,47 @@ import androidx.compose.ui.unit.dp
import org.schabi.newpipe.compose.theme.AppTheme import org.schabi.newpipe.compose.theme.AppTheme
import org.schabi.newpipe.extractor.stream.StreamInfoItem import org.schabi.newpipe.extractor.stream.StreamInfoItem
@OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun StreamGridItem(stream: StreamInfoItem, onClick: (StreamInfoItem) -> Unit) { fun StreamGridItem(
Column( stream: StreamInfoItem,
modifier = Modifier isSelected: Boolean = false,
.clickable(onClick = { onClick(stream) }) onClick: (StreamInfoItem) -> Unit = {},
.padding(12.dp) onLongClick: (StreamInfoItem) -> Unit = {},
) { onDismissPopup: () -> Unit = {}
StreamThumbnail(stream = stream, modifier = Modifier.size(width = 246.dp, height = 138.dp)) ) {
Box {
Column(
modifier = Modifier
.combinedClickable(
onLongClick = { onLongClick(stream) },
onClick = { onClick(stream) }
)
.padding(12.dp)
) {
StreamThumbnail(
modifier = Modifier.size(width = 246.dp, height = 138.dp),
stream = stream
)
Text( Text(
text = stream.name, text = stream.name,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleSmall, style = MaterialTheme.typography.titleSmall,
maxLines = 2 maxLines = 2
) )
Text(text = stream.uploaderName.orEmpty(), style = MaterialTheme.typography.bodySmall) Text(text = stream.uploaderName.orEmpty(), style = MaterialTheme.typography.bodySmall)
Text( Text(
text = getStreamInfoDetail(stream), text = getStreamInfoDetail(stream),
style = MaterialTheme.typography.bodySmall style = MaterialTheme.typography.bodySmall
) )
}
if (isSelected) {
StreamMenu(onDismissPopup)
}
} }
} }
@ -50,7 +71,7 @@ private fun StreamGridItemPreview(
) { ) {
AppTheme { AppTheme {
Surface(color = MaterialTheme.colorScheme.background) { Surface(color = MaterialTheme.colorScheme.background) {
StreamGridItem(stream, onClick = {}) StreamGridItem(stream)
} }
} }
} }

View File

@ -8,7 +8,10 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
@ -36,7 +39,20 @@ fun StreamList(
) )
} }
} }
// TODO: Handle long-click by showing a dropdown menu instead of a dialog.
// Handle long clicks
// TODO: Adjust the menu display depending on where it was triggered
var selectedStream by remember { mutableStateOf<StreamInfoItem?>(null) }
val onLongClick = remember {
{ stream: StreamInfoItem ->
selectedStream = stream
}
}
val onDismissPopup = remember {
{
selectedStream = null
}
}
if (mode == ItemViewMode.GRID) { if (mode == ItemViewMode.GRID) {
val gridState = rememberLazyGridState() val gridState = rememberLazyGridState()
@ -46,7 +62,11 @@ fun StreamList(
gridHeader() gridHeader()
items(streams.itemCount) { items(streams.itemCount) {
StreamGridItem(streams[it]!!, onClick) val stream = streams[it]!!
StreamGridItem(
stream, selectedStream == stream, onClick, onLongClick,
onDismissPopup
)
} }
} }
} }
@ -60,10 +80,12 @@ fun StreamList(
items(streams.itemCount) { items(streams.itemCount) {
val stream = streams[it]!! val stream = streams[it]!!
val isSelected = selectedStream == stream
if (mode == ItemViewMode.CARD) { if (mode == ItemViewMode.CARD) {
StreamCardItem(stream, onClick) StreamCardItem(stream, isSelected, onClick, onLongClick, onDismissPopup)
} else { } else {
StreamListItem(stream, onClick) StreamListItem(stream, isSelected, onClick, onLongClick, onDismissPopup)
} }
} }
} }

View File

@ -1,8 +1,10 @@
package org.schabi.newpipe.compose.stream package org.schabi.newpipe.compose.stream
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.foundation.clickable import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -21,32 +23,51 @@ import androidx.compose.ui.unit.dp
import org.schabi.newpipe.compose.theme.AppTheme import org.schabi.newpipe.compose.theme.AppTheme
import org.schabi.newpipe.extractor.stream.StreamInfoItem import org.schabi.newpipe.extractor.stream.StreamInfoItem
@OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
fun StreamListItem(stream: StreamInfoItem, onClick: (StreamInfoItem) -> Unit) { fun StreamListItem(
Row( stream: StreamInfoItem,
modifier = Modifier isSelected: Boolean = false,
.clickable(onClick = { onClick(stream) }) onClick: (StreamInfoItem) -> Unit = {},
.fillMaxWidth() onLongClick: (StreamInfoItem) -> Unit = {},
.padding(12.dp), onDismissPopup: () -> Unit = {}
horizontalArrangement = Arrangement.spacedBy(4.dp), ) {
verticalAlignment = Alignment.CenterVertically Box {
) { Row(
StreamThumbnail(stream = stream, modifier = Modifier.size(width = 98.dp, height = 55.dp)) modifier = Modifier
.combinedClickable(
Column { onLongClick = { onLongClick(stream) },
Text( onClick = { onClick(stream) }
text = stream.name, )
overflow = TextOverflow.Ellipsis, .fillMaxWidth()
style = MaterialTheme.typography.titleSmall, .padding(12.dp),
maxLines = 1 horizontalArrangement = Arrangement.spacedBy(4.dp),
verticalAlignment = Alignment.CenterVertically
) {
StreamThumbnail(
modifier = Modifier.size(width = 98.dp, height = 55.dp),
stream = stream
) )
Text(text = stream.uploaderName.orEmpty(), style = MaterialTheme.typography.bodySmall) Column {
Text(
text = stream.name,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleSmall,
maxLines = 1
)
Text( Text(text = stream.uploaderName.orEmpty(), style = MaterialTheme.typography.bodySmall)
text = getStreamInfoDetail(stream),
style = MaterialTheme.typography.bodySmall Text(
) text = getStreamInfoDetail(stream),
style = MaterialTheme.typography.bodySmall
)
}
}
if (isSelected) {
StreamMenu(onDismissPopup)
} }
} }
} }
@ -59,7 +80,7 @@ private fun StreamListItemPreview(
) { ) {
AppTheme { AppTheme {
Surface(color = MaterialTheme.colorScheme.background) { Surface(color = MaterialTheme.colorScheme.background) {
StreamListItem(stream, onClick = {}) StreamListItem(stream)
} }
} }
} }

View File

@ -0,0 +1,46 @@
package org.schabi.newpipe.compose.stream
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import org.schabi.newpipe.R
@Composable
fun StreamMenu(onDismissRequest: () -> Unit) {
DropdownMenu(expanded = true, onDismissRequest = onDismissRequest) {
DropdownMenuItem(
text = { Text(text = stringResource(R.string.start_here_on_background)) },
onClick = onDismissRequest
)
DropdownMenuItem(
text = { Text(text = stringResource(R.string.start_here_on_popup)) },
onClick = onDismissRequest
)
DropdownMenuItem(
text = { Text(text = stringResource(R.string.download)) },
onClick = onDismissRequest
)
DropdownMenuItem(
text = { Text(text = stringResource(R.string.add_to_playlist)) },
onClick = onDismissRequest
)
DropdownMenuItem(
text = { Text(text = stringResource(R.string.share)) },
onClick = onDismissRequest
)
DropdownMenuItem(
text = { Text(text = stringResource(R.string.open_in_browser)) },
onClick = onDismissRequest
)
DropdownMenuItem(
text = { Text(text = stringResource(R.string.mark_as_watched)) },
onClick = onDismissRequest
)
DropdownMenuItem(
text = { Text(text = stringResource(R.string.show_channel_details)) },
onClick = onDismissRequest
)
}
}

View File

@ -20,9 +20,9 @@ import org.schabi.newpipe.util.image.ImageStrategy
@Composable @Composable
fun StreamThumbnail( fun StreamThumbnail(
stream: StreamInfoItem,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
contentScale: ContentScale = ContentScale.Fit, stream: StreamInfoItem,
contentScale: ContentScale = ContentScale.Fit
) { ) {
Box(modifier = modifier, contentAlignment = Alignment.BottomEnd) { Box(modifier = modifier, contentAlignment = Alignment.BottomEnd) {
AsyncImage( AsyncImage(