mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	Improved stream components
This commit is contained in:
		| @@ -69,7 +69,7 @@ fun StreamCardItem( | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (isSelected) { |         if (isSelected) { | ||||||
|             StreamMenu(onDismissPopup) |             StreamMenu(stream, onDismissPopup) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ import androidx.compose.ui.Modifier | |||||||
| import androidx.compose.ui.text.style.TextOverflow | import androidx.compose.ui.text.style.TextOverflow | ||||||
| import androidx.compose.ui.tooling.preview.Preview | import androidx.compose.ui.tooling.preview.Preview | ||||||
| import androidx.compose.ui.tooling.preview.PreviewParameter | import androidx.compose.ui.tooling.preview.PreviewParameter | ||||||
|  | import androidx.compose.ui.unit.DpSize | ||||||
| import androidx.compose.ui.unit.dp | import androidx.compose.ui.unit.dp | ||||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem | import org.schabi.newpipe.extractor.stream.StreamInfoItem | ||||||
| import org.schabi.newpipe.ui.theme.AppTheme | import org.schabi.newpipe.ui.theme.AppTheme | ||||||
| @@ -24,6 +25,7 @@ import org.schabi.newpipe.ui.theme.AppTheme | |||||||
| fun StreamGridItem( | fun StreamGridItem( | ||||||
|     stream: StreamInfoItem, |     stream: StreamInfoItem, | ||||||
|     isSelected: Boolean = false, |     isSelected: Boolean = false, | ||||||
|  |     isMini: Boolean = false, | ||||||
|     onClick: (StreamInfoItem) -> Unit = {}, |     onClick: (StreamInfoItem) -> Unit = {}, | ||||||
|     onLongClick: (StreamInfoItem) -> Unit = {}, |     onLongClick: (StreamInfoItem) -> Unit = {}, | ||||||
|     onDismissPopup: () -> Unit = {} |     onDismissPopup: () -> Unit = {} | ||||||
| @@ -37,10 +39,9 @@ fun StreamGridItem( | |||||||
|                 ) |                 ) | ||||||
|                 .padding(12.dp) |                 .padding(12.dp) | ||||||
|         ) { |         ) { | ||||||
|             StreamThumbnail( |             val size = if (isMini) DpSize(150.dp, 85.dp) else DpSize(246.dp, 138.dp) | ||||||
|                 modifier = Modifier.size(width = 246.dp, height = 138.dp), |  | ||||||
|                 stream = stream |             StreamThumbnail(modifier = Modifier.size(size), stream = stream) | ||||||
|             ) |  | ||||||
|  |  | ||||||
|             Text( |             Text( | ||||||
|                 text = stream.name, |                 text = stream.name, | ||||||
| @@ -58,7 +59,7 @@ fun StreamGridItem( | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (isSelected) { |         if (isSelected) { | ||||||
|             StreamMenu(onDismissPopup) |             StreamMenu(stream, onDismissPopup) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import androidx.compose.foundation.lazy.grid.LazyGridScope | |||||||
| import androidx.compose.foundation.lazy.grid.LazyVerticalGrid | 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.material3.adaptive.currentWindowAdaptiveInfo | ||||||
| import androidx.compose.runtime.Composable | import androidx.compose.runtime.Composable | ||||||
| import androidx.compose.runtime.getValue | import androidx.compose.runtime.getValue | ||||||
| import androidx.compose.runtime.mutableStateOf | import androidx.compose.runtime.mutableStateOf | ||||||
| @@ -16,6 +17,7 @@ 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 | ||||||
| import androidx.paging.compose.LazyPagingItems | import androidx.paging.compose.LazyPagingItems | ||||||
|  | import androidx.window.core.layout.WindowWidthSizeClass | ||||||
| import my.nanihadesuka.compose.LazyColumnScrollbar | import my.nanihadesuka.compose.LazyColumnScrollbar | ||||||
| import my.nanihadesuka.compose.LazyVerticalGridScrollbar | import my.nanihadesuka.compose.LazyVerticalGridScrollbar | ||||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem | import org.schabi.newpipe.extractor.stream.StreamInfoItem | ||||||
| @@ -58,13 +60,17 @@ fun StreamList( | |||||||
|         val gridState = rememberLazyGridState() |         val gridState = rememberLazyGridState() | ||||||
|  |  | ||||||
|         LazyVerticalGridScrollbar(state = gridState) { |         LazyVerticalGridScrollbar(state = gridState) { | ||||||
|             LazyVerticalGrid(state = gridState, columns = GridCells.Adaptive(250.dp)) { |             val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass | ||||||
|  |             val isCompact = windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT | ||||||
|  |             val minSize = if (isCompact) 150.dp else 250.dp | ||||||
|  |  | ||||||
|  |             LazyVerticalGrid(state = gridState, columns = GridCells.Adaptive(minSize)) { | ||||||
|                 gridHeader() |                 gridHeader() | ||||||
|  |  | ||||||
|                 items(streams.itemCount) { |                 items(streams.itemCount) { | ||||||
|                     val stream = streams[it]!! |                     val stream = streams[it]!! | ||||||
|                     StreamGridItem( |                     StreamGridItem( | ||||||
|                         stream, selectedStream == stream, onClick, onLongClick, |                         stream, selectedStream == stream, isCompact, onClick, onLongClick, | ||||||
|                         onDismissPopup |                         onDismissPopup | ||||||
|                     ) |                     ) | ||||||
|                 } |                 } | ||||||
|   | |||||||
| @@ -67,7 +67,7 @@ fun StreamListItem( | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (isSelected) { |         if (isSelected) { | ||||||
|             StreamMenu(onDismissPopup) |             StreamMenu(stream, onDismissPopup) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,11 +4,24 @@ import androidx.compose.material3.DropdownMenu | |||||||
| import androidx.compose.material3.DropdownMenuItem | import androidx.compose.material3.DropdownMenuItem | ||||||
| import androidx.compose.material3.Text | import androidx.compose.material3.Text | ||||||
| import androidx.compose.runtime.Composable | import androidx.compose.runtime.Composable | ||||||
|  | import androidx.compose.ui.platform.LocalContext | ||||||
| import androidx.compose.ui.res.stringResource | import androidx.compose.ui.res.stringResource | ||||||
|  | import androidx.fragment.app.FragmentActivity | ||||||
| import org.schabi.newpipe.R | import org.schabi.newpipe.R | ||||||
|  | import org.schabi.newpipe.download.DownloadDialog | ||||||
|  | import org.schabi.newpipe.extractor.stream.StreamInfo | ||||||
|  | import org.schabi.newpipe.extractor.stream.StreamInfoItem | ||||||
|  | import org.schabi.newpipe.util.SparseItemUtil | ||||||
|  | import org.schabi.newpipe.util.external_communication.ShareUtils | ||||||
|  |  | ||||||
| @Composable | @Composable | ||||||
| fun StreamMenu(onDismissRequest: () -> Unit) { | fun StreamMenu( | ||||||
|  |     stream: StreamInfoItem, | ||||||
|  |     onDismissRequest: () -> Unit | ||||||
|  | ) { | ||||||
|  |     val context = LocalContext.current | ||||||
|  |  | ||||||
|  |     // TODO: Implement remaining click actions | ||||||
|     DropdownMenu(expanded = true, onDismissRequest = onDismissRequest) { |     DropdownMenu(expanded = true, onDismissRequest = onDismissRequest) { | ||||||
|         DropdownMenuItem( |         DropdownMenuItem( | ||||||
|             text = { Text(text = stringResource(R.string.start_here_on_background)) }, |             text = { Text(text = stringResource(R.string.start_here_on_background)) }, | ||||||
| @@ -20,7 +33,15 @@ fun StreamMenu(onDismissRequest: () -> Unit) { | |||||||
|         ) |         ) | ||||||
|         DropdownMenuItem( |         DropdownMenuItem( | ||||||
|             text = { Text(text = stringResource(R.string.download)) }, |             text = { Text(text = stringResource(R.string.download)) }, | ||||||
|             onClick = onDismissRequest |             onClick = { | ||||||
|  |                 SparseItemUtil.fetchStreamInfoAndSaveToDatabase( | ||||||
|  |                     context, stream.serviceId, stream.url | ||||||
|  |                 ) { info: StreamInfo -> | ||||||
|  |                     val downloadDialog = DownloadDialog(context, info) | ||||||
|  |                     val fragmentManager = (context as FragmentActivity).supportFragmentManager | ||||||
|  |                     downloadDialog.show(fragmentManager, "downloadDialog") | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         ) |         ) | ||||||
|         DropdownMenuItem( |         DropdownMenuItem( | ||||||
|             text = { Text(text = stringResource(R.string.add_to_playlist)) }, |             text = { Text(text = stringResource(R.string.add_to_playlist)) }, | ||||||
| @@ -28,11 +49,11 @@ fun StreamMenu(onDismissRequest: () -> Unit) { | |||||||
|         ) |         ) | ||||||
|         DropdownMenuItem( |         DropdownMenuItem( | ||||||
|             text = { Text(text = stringResource(R.string.share)) }, |             text = { Text(text = stringResource(R.string.share)) }, | ||||||
|             onClick = onDismissRequest |             onClick = { ShareUtils.shareText(context, stream.name, stream.url, stream.thumbnails) } | ||||||
|         ) |         ) | ||||||
|         DropdownMenuItem( |         DropdownMenuItem( | ||||||
|             text = { Text(text = stringResource(R.string.open_in_browser)) }, |             text = { Text(text = stringResource(R.string.open_in_browser)) }, | ||||||
|             onClick = onDismissRequest |             onClick = { ShareUtils.openUrlInBrowser(context, stream.url) } | ||||||
|         ) |         ) | ||||||
|         DropdownMenuItem( |         DropdownMenuItem( | ||||||
|             text = { Text(text = stringResource(R.string.mark_as_watched)) }, |             text = { Text(text = stringResource(R.string.mark_as_watched)) }, | ||||||
|   | |||||||
| @@ -11,11 +11,13 @@ import androidx.compose.ui.Modifier | |||||||
| import androidx.compose.ui.graphics.Color | import androidx.compose.ui.graphics.Color | ||||||
| import androidx.compose.ui.layout.ContentScale | import androidx.compose.ui.layout.ContentScale | ||||||
| import androidx.compose.ui.res.painterResource | import androidx.compose.ui.res.painterResource | ||||||
|  | import androidx.compose.ui.res.stringResource | ||||||
| import androidx.compose.ui.unit.dp | import androidx.compose.ui.unit.dp | ||||||
| import coil.compose.AsyncImage | import coil.compose.AsyncImage | ||||||
| import org.schabi.newpipe.R | import org.schabi.newpipe.R | ||||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem | import org.schabi.newpipe.extractor.stream.StreamInfoItem | ||||||
| import org.schabi.newpipe.util.Localization | import org.schabi.newpipe.util.Localization | ||||||
|  | import org.schabi.newpipe.util.StreamTypeUtil | ||||||
| import org.schabi.newpipe.util.image.ImageStrategy | import org.schabi.newpipe.util.image.ImageStrategy | ||||||
|  |  | ||||||
| @Composable | @Composable | ||||||
| @@ -34,12 +36,19 @@ fun StreamThumbnail( | |||||||
|             modifier = modifier |             modifier = modifier | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |         val isLive = StreamTypeUtil.isLiveStream(stream.streamType) | ||||||
|  |         val background = if (isLive) Color.Red else Color.Black | ||||||
|         Text( |         Text( | ||||||
|             text = Localization.getDurationString(stream.duration), |             text = if (isLive) { | ||||||
|  |                 stringResource(R.string.duration_live) | ||||||
|  |             } else { | ||||||
|  |                 Localization.getDurationString(stream.duration) | ||||||
|  |             }, | ||||||
|             color = Color.White, |             color = Color.White, | ||||||
|             style = MaterialTheme.typography.bodySmall, |             style = MaterialTheme.typography.bodySmall, | ||||||
|             modifier = Modifier.padding(2.dp) |             modifier = Modifier | ||||||
|                 .background(Color.Black.copy(alpha = 0.5f)) |                 .padding(2.dp) | ||||||
|  |                 .background(background.copy(alpha = 0.5f)) | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Isira Seneviratne
					Isira Seneviratne