mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-05 01:39:08 +00:00
feat(library): Add view all functionality for library sections and internal library fetching
This commit is contained in:
parent
39a5d57f15
commit
054cb7a049
3 changed files with 81 additions and 1 deletions
|
|
@ -66,6 +66,7 @@ import com.nuvio.app.core.ui.NuvioTheme
|
|||
import com.nuvio.app.features.auth.AuthScreen
|
||||
import com.nuvio.app.features.catalog.CatalogRepository
|
||||
import com.nuvio.app.features.catalog.CatalogScreen
|
||||
import com.nuvio.app.features.catalog.INTERNAL_LIBRARY_MANIFEST_URL
|
||||
import com.nuvio.app.features.details.MetaDetailsRepository
|
||||
import com.nuvio.app.features.details.MetaDetailsScreen
|
||||
import com.nuvio.app.features.home.HomeCatalogSection
|
||||
|
|
@ -73,6 +74,8 @@ import com.nuvio.app.features.home.HomeScreen
|
|||
import com.nuvio.app.features.home.MetaPreview
|
||||
import com.nuvio.app.features.library.LibraryItem
|
||||
import com.nuvio.app.features.library.LibraryRepository
|
||||
import com.nuvio.app.features.library.LibrarySection
|
||||
import com.nuvio.app.features.library.LibrarySourceMode
|
||||
import com.nuvio.app.features.library.LibraryScreen
|
||||
import com.nuvio.app.features.library.toLibraryItem
|
||||
import com.nuvio.app.features.player.PlayerLaunch
|
||||
|
|
@ -340,6 +343,23 @@ private fun MainAppContent(
|
|||
)
|
||||
}
|
||||
|
||||
val onLibrarySectionViewAllClick: (LibrarySection) -> Unit = { section ->
|
||||
navController.navigate(
|
||||
CatalogRoute(
|
||||
title = section.displayTitle,
|
||||
subtitle = if (libraryUiState.sourceMode == LibrarySourceMode.TRAKT) {
|
||||
"Trakt Library"
|
||||
} else {
|
||||
"Library"
|
||||
},
|
||||
manifestUrl = INTERNAL_LIBRARY_MANIFEST_URL,
|
||||
type = section.items.firstOrNull()?.type ?: "movie",
|
||||
catalogId = section.type,
|
||||
supportsPagination = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val onContinueWatchingClick: (ContinueWatchingItem) -> Unit = { item ->
|
||||
val streamContextId = item.pauseDescription
|
||||
?.takeIf { it.isNotBlank() }
|
||||
|
|
@ -460,6 +480,7 @@ private fun MainAppContent(
|
|||
onLibraryPosterClick = { item ->
|
||||
navController.navigate(DetailRoute(type = item.type, id = item.id))
|
||||
},
|
||||
onLibrarySectionViewAllClick = onLibrarySectionViewAllClick,
|
||||
onContinueWatchingClick = onContinueWatchingClick,
|
||||
onContinueWatchingLongPress = onContinueWatchingLongPress,
|
||||
onSwitchProfile = onSwitchProfile,
|
||||
|
|
@ -758,6 +779,7 @@ private fun AppTabHost(
|
|||
onPosterClick: ((MetaPreview) -> Unit)? = null,
|
||||
onPosterLongClick: ((MetaPreview) -> Unit)? = null,
|
||||
onLibraryPosterClick: ((LibraryItem) -> Unit)? = null,
|
||||
onLibrarySectionViewAllClick: ((LibrarySection) -> Unit)? = null,
|
||||
onContinueWatchingClick: ((ContinueWatchingItem) -> Unit)? = null,
|
||||
onContinueWatchingLongPress: ((ContinueWatchingItem) -> Unit)? = null,
|
||||
onSwitchProfile: (() -> Unit)? = null,
|
||||
|
|
@ -796,6 +818,7 @@ private fun AppTabHost(
|
|||
LibraryScreen(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
onPosterClick = onLibraryPosterClick,
|
||||
onSectionViewAllClick = onLibrarySectionViewAllClick,
|
||||
)
|
||||
}
|
||||
keepAliveTab(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.nuvio.app.features.catalog
|
||||
|
||||
import com.nuvio.app.features.library.LibraryRepository
|
||||
import com.nuvio.app.features.library.toMetaPreview
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
|
|
@ -9,6 +11,8 @@ import kotlinx.coroutines.flow.StateFlow
|
|||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
const val INTERNAL_LIBRARY_MANIFEST_URL = "nuvio://library"
|
||||
|
||||
object CatalogRepository {
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
private val _uiState = MutableStateFlow(CatalogUiState())
|
||||
|
|
@ -36,6 +40,10 @@ object CatalogRepository {
|
|||
return
|
||||
}
|
||||
activeRequest = request
|
||||
if (manifestUrl == INTERNAL_LIBRARY_MANIFEST_URL) {
|
||||
fetchInternalLibrary(request)
|
||||
return
|
||||
}
|
||||
fetchPage(request = request, reset = true)
|
||||
}
|
||||
|
||||
|
|
@ -52,6 +60,44 @@ object CatalogRepository {
|
|||
_uiState.value = CatalogUiState()
|
||||
}
|
||||
|
||||
private fun fetchInternalLibrary(request: CatalogRequest) {
|
||||
activeJob?.cancel()
|
||||
_uiState.value = _uiState.value.copy(
|
||||
isLoading = true,
|
||||
errorMessage = null,
|
||||
)
|
||||
|
||||
activeJob = scope.launch {
|
||||
runCatching {
|
||||
LibraryRepository.ensureLoaded()
|
||||
LibraryRepository.uiState.value.sections
|
||||
.firstOrNull { it.type == request.catalogId }
|
||||
?.items
|
||||
.orEmpty()
|
||||
.map { it.toMetaPreview() }
|
||||
}.fold(
|
||||
onSuccess = { items ->
|
||||
if (activeRequest != request) return@fold
|
||||
_uiState.value = CatalogUiState(
|
||||
items = items,
|
||||
isLoading = false,
|
||||
nextSkip = null,
|
||||
errorMessage = null,
|
||||
)
|
||||
},
|
||||
onFailure = { error ->
|
||||
if (activeRequest != request) return@fold
|
||||
_uiState.value = CatalogUiState(
|
||||
items = emptyList(),
|
||||
isLoading = false,
|
||||
nextSkip = null,
|
||||
errorMessage = error.message ?: "Unable to load catalog items.",
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchPage(
|
||||
request: CatalogRequest,
|
||||
reset: Boolean,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.nuvio.app.features.home.components.HomePosterCard
|
|||
fun LibraryScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
onPosterClick: ((LibraryItem) -> Unit)? = null,
|
||||
onSectionViewAllClick: ((LibrarySection) -> Unit)? = null,
|
||||
) {
|
||||
val uiState by remember {
|
||||
LibraryRepository.ensureLoaded()
|
||||
|
|
@ -74,6 +75,7 @@ fun LibraryScreen(
|
|||
librarySections(
|
||||
sections = uiState.sections,
|
||||
onPosterClick = onPosterClick,
|
||||
onSectionViewAllClick = onSectionViewAllClick,
|
||||
onPosterLongClick = { item ->
|
||||
if (!isTraktSource) {
|
||||
pendingRemovalItem = item
|
||||
|
|
@ -101,17 +103,24 @@ fun LibraryScreen(
|
|||
private fun LazyListScope.librarySections(
|
||||
sections: List<LibrarySection>,
|
||||
onPosterClick: ((LibraryItem) -> Unit)?,
|
||||
onSectionViewAllClick: ((LibrarySection) -> Unit)?,
|
||||
onPosterLongClick: (LibraryItem) -> Unit,
|
||||
) {
|
||||
items(
|
||||
items = sections,
|
||||
key = { section -> section.type },
|
||||
) { section ->
|
||||
val previewItems = section.items.take(LIBRARY_SECTION_PREVIEW_LIMIT)
|
||||
NuvioShelfSection(
|
||||
title = section.displayTitle,
|
||||
entries = section.items,
|
||||
entries = previewItems,
|
||||
headerHorizontalPadding = 16.dp,
|
||||
rowContentPadding = PaddingValues(horizontal = 16.dp),
|
||||
onViewAllClick = if (section.items.size > LIBRARY_SECTION_PREVIEW_LIMIT) {
|
||||
onSectionViewAllClick?.let { { it(section) } }
|
||||
} else {
|
||||
null
|
||||
},
|
||||
viewAllPillSize = NuvioViewAllPillSize.Compact,
|
||||
key = { item -> "${item.type}:${item.id}" },
|
||||
) { item ->
|
||||
|
|
@ -123,3 +132,5 @@ private fun LazyListScope.librarySections(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val LIBRARY_SECTION_PREVIEW_LIMIT = 18
|
||||
|
|
|
|||
Loading…
Reference in a new issue