Skip to content

Commit ec30266

Browse files
Moved stream display to separate composable for reusability
1 parent 62a405d commit ec30266

File tree

2 files changed

+97
-83
lines changed

2 files changed

+97
-83
lines changed
Lines changed: 25 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,55 @@
11
package org.schabi.newpipe.compose.playlist
22

33
import android.content.res.Configuration
4-
import androidx.compose.foundation.lazy.LazyColumn
5-
import androidx.compose.foundation.lazy.grid.GridCells
64
import androidx.compose.foundation.lazy.grid.GridItemSpan
7-
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
8-
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
9-
import androidx.compose.foundation.lazy.rememberLazyListState
105
import androidx.compose.material3.MaterialTheme
116
import androidx.compose.material3.Surface
127
import androidx.compose.runtime.Composable
138
import androidx.compose.runtime.collectAsState
149
import androidx.compose.runtime.derivedStateOf
1510
import androidx.compose.runtime.getValue
1611
import androidx.compose.runtime.remember
17-
import androidx.compose.ui.platform.LocalContext
1812
import androidx.compose.ui.tooling.preview.Preview
19-
import androidx.compose.ui.unit.dp
20-
import androidx.fragment.app.FragmentActivity
13+
import androidx.lifecycle.SavedStateHandle
2114
import androidx.lifecycle.viewmodel.compose.viewModel
22-
import androidx.paging.Pager
23-
import androidx.paging.PagingConfig
24-
import androidx.paging.PagingData
2515
import androidx.paging.compose.collectAsLazyPagingItems
26-
import kotlinx.coroutines.flow.Flow
27-
import my.nanihadesuka.compose.LazyColumnScrollbar
28-
import my.nanihadesuka.compose.LazyVerticalGridScrollbar
2916
import org.schabi.newpipe.DownloaderImpl
3017
import org.schabi.newpipe.compose.status.LoadingIndicator
31-
import org.schabi.newpipe.compose.stream.StreamCardItem
32-
import org.schabi.newpipe.compose.stream.StreamGridItem
33-
import org.schabi.newpipe.compose.stream.StreamListItem
18+
import org.schabi.newpipe.compose.stream.StreamList
3419
import org.schabi.newpipe.compose.theme.AppTheme
35-
import org.schabi.newpipe.compose.util.determineItemViewMode
3620
import org.schabi.newpipe.extractor.NewPipe
3721
import org.schabi.newpipe.extractor.ServiceList
38-
import org.schabi.newpipe.extractor.playlist.PlaylistInfo
39-
import org.schabi.newpipe.extractor.stream.StreamInfoItem
40-
import org.schabi.newpipe.info_list.ItemViewMode
41-
import org.schabi.newpipe.paging.PlaylistItemsSource
42-
import org.schabi.newpipe.util.NavigationHelper
22+
import org.schabi.newpipe.util.KEY_SERVICE_ID
23+
import org.schabi.newpipe.util.KEY_URL
4324
import org.schabi.newpipe.viewmodels.PlaylistViewModel
4425

4526
@Composable
4627
fun Playlist(playlistViewModel: PlaylistViewModel = viewModel()) {
4728
Surface(color = MaterialTheme.colorScheme.background) {
4829
val playlistInfo by playlistViewModel.playlistInfo.collectAsState()
49-
playlistInfo?.let {
50-
LoadedPlaylist(it, playlistViewModel.streamItems)
51-
} ?: LoadingIndicator()
52-
}
53-
}
54-
55-
@Composable
56-
private fun LoadedPlaylist(playlistInfo: PlaylistInfo, flow: Flow<PagingData<StreamInfoItem>>) {
57-
val streams = flow.collectAsLazyPagingItems()
58-
val mode = determineItemViewMode()
59-
val context = LocalContext.current
60-
61-
val totalDuration by remember {
62-
derivedStateOf {
63-
streams.itemSnapshotList.sumOf { it!!.duration }
64-
}
65-
}
66-
val onClick = { stream: StreamInfoItem ->
67-
NavigationHelper.openVideoDetailFragment(
68-
context, (context as FragmentActivity).supportFragmentManager,
69-
stream.serviceId, stream.url, stream.name, null, false
70-
)
71-
}
72-
73-
if (mode == ItemViewMode.GRID) {
74-
val gridState = rememberLazyGridState()
7530

76-
LazyVerticalGridScrollbar(state = gridState) {
77-
LazyVerticalGrid(state = gridState, columns = GridCells.Adaptive(250.dp)) {
78-
item(span = { GridItemSpan(maxLineSpan) }) {
79-
PlaylistHeader(playlistInfo, totalDuration)
80-
}
81-
82-
items(streams.itemCount) {
83-
StreamGridItem(streams[it]!!, onClick)
31+
playlistInfo?.let {
32+
val streams = playlistViewModel.streamItems.collectAsLazyPagingItems()
33+
val totalDuration by remember {
34+
derivedStateOf {
35+
streams.itemSnapshotList.sumOf { it!!.duration }
8436
}
8537
}
86-
}
87-
} else {
88-
// Card or list views
89-
val listState = rememberLazyListState()
90-
91-
LazyColumnScrollbar(state = listState) {
92-
LazyColumn(state = listState) {
93-
item {
94-
PlaylistHeader(playlistInfo, totalDuration)
95-
}
9638

97-
items(streams.itemCount) {
98-
val stream = streams[it]!!
99-
if (mode == ItemViewMode.CARD) {
100-
StreamCardItem(stream, onClick)
101-
} else {
102-
StreamListItem(stream, onClick)
39+
StreamList(
40+
streams = streams,
41+
gridHeader = {
42+
item(span = { GridItemSpan(maxLineSpan) }) {
43+
PlaylistHeader(it, totalDuration)
44+
}
45+
},
46+
listHeader = {
47+
item {
48+
PlaylistHeader(it, totalDuration)
10349
}
10450
}
105-
}
106-
}
51+
)
52+
} ?: LoadingIndicator()
10753
}
10854
}
10955

@@ -113,17 +59,13 @@ private fun LoadedPlaylist(playlistInfo: PlaylistInfo, flow: Flow<PagingData<Str
11359
private fun PlaylistPreview() {
11460
NewPipe.init(DownloaderImpl.init(null))
11561

116-
val playlistInfo = PlaylistInfo.getInfo(
117-
ServiceList.YouTube,
118-
"https://www.youtube.com/playlist?list=PLAIcZs9N4171hRrG_4v32Ca2hLvSuQ6QI"
62+
val params = mapOf(
63+
KEY_SERVICE_ID to ServiceList.YouTube.serviceId,
64+
KEY_URL to "https://www.youtube.com/playlist?list=PLAIcZs9N4171hRrG_4v32Ca2hLvSuQ6QI"
11965
)
120-
val streams = Pager(PagingConfig(pageSize = 20, enablePlaceholders = false)) {
121-
PlaylistItemsSource(playlistInfo)
122-
}.flow
123-
12466
AppTheme {
12567
Surface(color = MaterialTheme.colorScheme.background) {
126-
LoadedPlaylist(playlistInfo, streams)
68+
Playlist(PlaylistViewModel(SavedStateHandle(params)))
12769
}
12870
}
12971
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package org.schabi.newpipe.compose.stream
2+
3+
import androidx.compose.foundation.lazy.LazyColumn
4+
import androidx.compose.foundation.lazy.LazyListScope
5+
import androidx.compose.foundation.lazy.grid.GridCells
6+
import androidx.compose.foundation.lazy.grid.LazyGridScope
7+
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
8+
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
9+
import androidx.compose.foundation.lazy.rememberLazyListState
10+
import androidx.compose.runtime.Composable
11+
import androidx.compose.runtime.remember
12+
import androidx.compose.ui.platform.LocalContext
13+
import androidx.compose.ui.unit.dp
14+
import androidx.fragment.app.FragmentActivity
15+
import androidx.paging.compose.LazyPagingItems
16+
import my.nanihadesuka.compose.LazyColumnScrollbar
17+
import my.nanihadesuka.compose.LazyVerticalGridScrollbar
18+
import org.schabi.newpipe.compose.util.determineItemViewMode
19+
import org.schabi.newpipe.extractor.stream.StreamInfoItem
20+
import org.schabi.newpipe.info_list.ItemViewMode
21+
import org.schabi.newpipe.util.NavigationHelper
22+
23+
@Composable
24+
fun StreamList(
25+
streams: LazyPagingItems<StreamInfoItem>,
26+
gridHeader: LazyGridScope.() -> Unit = {},
27+
listHeader: LazyListScope.() -> Unit = {}
28+
) {
29+
val mode = determineItemViewMode()
30+
val context = LocalContext.current
31+
val onClick = remember {
32+
{ stream: StreamInfoItem ->
33+
NavigationHelper.openVideoDetailFragment(
34+
context, (context as FragmentActivity).supportFragmentManager,
35+
stream.serviceId, stream.url, stream.name, null, false
36+
)
37+
}
38+
}
39+
// TODO: Handle long-click by showing a dropdown menu instead of a dialog.
40+
41+
if (mode == ItemViewMode.GRID) {
42+
val gridState = rememberLazyGridState()
43+
44+
LazyVerticalGridScrollbar(state = gridState) {
45+
LazyVerticalGrid(state = gridState, columns = GridCells.Adaptive(250.dp)) {
46+
gridHeader()
47+
48+
items(streams.itemCount) {
49+
StreamGridItem(streams[it]!!, onClick)
50+
}
51+
}
52+
}
53+
} else {
54+
// Card or list views
55+
val listState = rememberLazyListState()
56+
57+
LazyColumnScrollbar(state = listState) {
58+
LazyColumn(state = listState) {
59+
listHeader()
60+
61+
items(streams.itemCount) {
62+
val stream = streams[it]!!
63+
if (mode == ItemViewMode.CARD) {
64+
StreamCardItem(stream, onClick)
65+
} else {
66+
StreamListItem(stream, onClick)
67+
}
68+
}
69+
}
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)