mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-16 23:12:12 +00:00
feat: add genre support to catalog sources and update UI accordingly
This commit is contained in:
parent
d44d3ea002
commit
7727436272
5 changed files with 77 additions and 3 deletions
|
|
@ -202,10 +202,12 @@ object CollectionEditorRepository {
|
||||||
|
|
||||||
fun addCatalogSource(catalog: AvailableCatalog) {
|
fun addCatalogSource(catalog: AvailableCatalog) {
|
||||||
val folder = _uiState.value.editingFolder ?: return
|
val folder = _uiState.value.editingFolder ?: return
|
||||||
|
val defaultGenre = if (catalog.genreRequired) catalog.genreOptions.firstOrNull() else null
|
||||||
val source = CollectionCatalogSource(
|
val source = CollectionCatalogSource(
|
||||||
addonId = catalog.addonId,
|
addonId = catalog.addonId,
|
||||||
type = catalog.type,
|
type = catalog.type,
|
||||||
catalogId = catalog.catalogId,
|
catalogId = catalog.catalogId,
|
||||||
|
genre = defaultGenre,
|
||||||
)
|
)
|
||||||
if (folder.catalogSources.any {
|
if (folder.catalogSources.any {
|
||||||
it.addonId == source.addonId && it.type == source.type && it.catalogId == source.catalogId
|
it.addonId == source.addonId && it.type == source.type && it.catalogId == source.catalogId
|
||||||
|
|
@ -225,6 +227,16 @@ object CollectionEditorRepository {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateCatalogSourceGenre(index: Int, genre: String?) {
|
||||||
|
val folder = _uiState.value.editingFolder ?: return
|
||||||
|
if (index !in folder.catalogSources.indices) return
|
||||||
|
val updated = folder.catalogSources.toMutableList()
|
||||||
|
updated[index] = updated[index].copy(genre = genre)
|
||||||
|
_uiState.value = _uiState.value.copy(
|
||||||
|
editingFolder = folder.copy(catalogSources = updated),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun toggleCatalogSource(catalog: AvailableCatalog) {
|
fun toggleCatalogSource(catalog: AvailableCatalog) {
|
||||||
val folder = _uiState.value.editingFolder ?: return
|
val folder = _uiState.value.editingFolder ?: return
|
||||||
val existingIndex = folder.catalogSources.indexOfFirst {
|
val existingIndex = folder.catalogSources.indexOfFirst {
|
||||||
|
|
|
||||||
|
|
@ -697,6 +697,10 @@ private fun FolderEditorSheet(
|
||||||
}
|
}
|
||||||
|
|
||||||
itemsIndexed(folder.catalogSources) { index, source ->
|
itemsIndexed(folder.catalogSources) { index, source ->
|
||||||
|
val matchingCatalog = state.availableCatalogs.find {
|
||||||
|
it.addonId == source.addonId && it.type == source.type && it.catalogId == source.catalogId
|
||||||
|
}
|
||||||
|
val genreOptions = matchingCatalog?.genreOptions.orEmpty()
|
||||||
NuvioSurfaceCard {
|
NuvioSurfaceCard {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
|
@ -711,7 +715,10 @@ private fun FolderEditorSheet(
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = source.addonId,
|
text = buildString {
|
||||||
|
append(source.addonId)
|
||||||
|
if (source.genre != null) append(" · ${source.genre}")
|
||||||
|
},
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
|
|
@ -730,6 +737,51 @@ private fun FolderEditorSheet(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (genreOptions.isNotEmpty()) {
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
text = "Genre",
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
FlowRow(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(6.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(6.dp),
|
||||||
|
) {
|
||||||
|
FilterChip(
|
||||||
|
selected = source.genre == null,
|
||||||
|
onClick = { CollectionEditorRepository.updateCatalogSourceGenre(index, null) },
|
||||||
|
label = { Text("All") },
|
||||||
|
leadingIcon = if (source.genre == null) {
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Rounded.Check,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(18.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else null,
|
||||||
|
)
|
||||||
|
genreOptions.forEach { genre ->
|
||||||
|
FilterChip(
|
||||||
|
selected = source.genre == genre,
|
||||||
|
onClick = { CollectionEditorRepository.updateCatalogSourceGenre(index, genre) },
|
||||||
|
label = { Text(genre) },
|
||||||
|
leadingIcon = if (source.genre == genre) {
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Rounded.Check,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(18.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ data class CollectionCatalogSource(
|
||||||
val addonId: String,
|
val addonId: String,
|
||||||
val type: String,
|
val type: String,
|
||||||
val catalogId: String,
|
val catalogId: String,
|
||||||
|
val genre: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
|
@ -73,6 +74,8 @@ data class AvailableCatalog(
|
||||||
val type: String,
|
val type: String,
|
||||||
val catalogId: String,
|
val catalogId: String,
|
||||||
val catalogName: String,
|
val catalogName: String,
|
||||||
|
val genreOptions: List<String> = emptyList(),
|
||||||
|
val genreRequired: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|
|
||||||
|
|
@ -157,14 +157,17 @@ object CollectionRepository {
|
||||||
addon to manifest
|
addon to manifest
|
||||||
}.flatMap { (addon, manifest) ->
|
}.flatMap { (addon, manifest) ->
|
||||||
manifest.catalogs
|
manifest.catalogs
|
||||||
.filter { catalog -> catalog.extra.none { it.isRequired } }
|
.filter { catalog -> catalog.extra.none { it.isRequired && it.name != "genre" } }
|
||||||
.map { catalog ->
|
.map { catalog ->
|
||||||
|
val genreExtra = catalog.extra.firstOrNull { it.name == "genre" }
|
||||||
AvailableCatalog(
|
AvailableCatalog(
|
||||||
addonId = manifest.id,
|
addonId = manifest.id,
|
||||||
addonName = addon.displayTitle,
|
addonName = addon.displayTitle,
|
||||||
type = catalog.type,
|
type = catalog.type,
|
||||||
catalogId = catalog.id,
|
catalogId = catalog.id,
|
||||||
catalogName = catalog.name,
|
catalogName = catalog.name,
|
||||||
|
genreOptions = genreExtra?.options.orEmpty(),
|
||||||
|
genreRequired = genreExtra?.isRequired == true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ data class FolderTab(
|
||||||
val manifestUrl: String? = null,
|
val manifestUrl: String? = null,
|
||||||
val type: String = "",
|
val type: String = "",
|
||||||
val catalogId: String = "",
|
val catalogId: String = "",
|
||||||
|
val genre: String? = null,
|
||||||
val supportsPagination: Boolean = false,
|
val supportsPagination: Boolean = false,
|
||||||
val items: List<MetaPreview> = emptyList(),
|
val items: List<MetaPreview> = emptyList(),
|
||||||
val isLoading: Boolean = true,
|
val isLoading: Boolean = true,
|
||||||
|
|
@ -123,13 +124,15 @@ object FolderDetailRepository {
|
||||||
val typeLabel = source.type.replaceFirstChar {
|
val typeLabel = source.type.replaceFirstChar {
|
||||||
if (it.isLowerCase()) it.titlecase() else it.toString()
|
if (it.isLowerCase()) it.titlecase() else it.toString()
|
||||||
}
|
}
|
||||||
|
val genreSuffix = if (source.genre != null) " · ${source.genre}" else ""
|
||||||
add(
|
add(
|
||||||
FolderTab(
|
FolderTab(
|
||||||
label = "$label ($typeLabel)",
|
label = "$label ($typeLabel)$genreSuffix",
|
||||||
typeLabel = typeLabel,
|
typeLabel = typeLabel,
|
||||||
manifestUrl = addon?.manifestUrl,
|
manifestUrl = addon?.manifestUrl,
|
||||||
type = source.type,
|
type = source.type,
|
||||||
catalogId = source.catalogId,
|
catalogId = source.catalogId,
|
||||||
|
genre = source.genre,
|
||||||
supportsPagination = catalog?.supportsPagination() == true,
|
supportsPagination = catalog?.supportsPagination() == true,
|
||||||
isLoading = true,
|
isLoading = true,
|
||||||
),
|
),
|
||||||
|
|
@ -236,6 +239,7 @@ object FolderDetailRepository {
|
||||||
manifestUrl = manifestUrl,
|
manifestUrl = manifestUrl,
|
||||||
type = currentTab.type,
|
type = currentTab.type,
|
||||||
catalogId = currentTab.catalogId,
|
catalogId = currentTab.catalogId,
|
||||||
|
genre = currentTab.genre,
|
||||||
skip = requestedSkip.takeIf { it > 0 },
|
skip = requestedSkip.takeIf { it > 0 },
|
||||||
)
|
)
|
||||||
}.onSuccess { page ->
|
}.onSuccess { page ->
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue