From 9cd3295d2ded1a1aebb9dfeef1ec47a11743789e Mon Sep 17 00:00:00 2001 From: Nelson Wu <50040940+nels0nwu@users.noreply.github.com> Date: Sun, 25 Feb 2024 03:48:03 +1100 Subject: [PATCH] feat: mixed libraries (#628) * mixed collection * Mixed libraries to show up in "Latest" Co-authored-by: Freya Winters * Do not recurse if folders are shown * Added folder navigation for tv * Removed assumption that folder == mixed * refactor: add default values to `FindroidFolder` * fix: add chapters to findroidfolder --------- Co-authored-by: Freya Winters Co-authored-by: Jarne Demeulemeester --- .../jellyfin/fragments/LibraryFragment.kt | 10 ++++++ .../main/res/navigation/app_navigation.xml | 3 ++ .../dev/jdtech/jellyfin/ui/LibraryScreen.kt | 5 +++ .../jellyfin/viewmodels/HomeViewModel.kt | 2 +- .../jellyfin/viewmodels/LibraryViewModel.kt | 6 +++- .../jdtech/jellyfin/models/CollectionType.kt | 6 ++-- .../jdtech/jellyfin/models/FindroidFolder.kt | 35 +++++++++++++++++++ .../jdtech/jellyfin/models/FindroidItem.kt | 1 + 8 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 data/src/main/java/dev/jdtech/jellyfin/models/FindroidFolder.kt diff --git a/app/phone/src/main/java/dev/jdtech/jellyfin/fragments/LibraryFragment.kt b/app/phone/src/main/java/dev/jdtech/jellyfin/fragments/LibraryFragment.kt index c5a3c257..71223f7e 100644 --- a/app/phone/src/main/java/dev/jdtech/jellyfin/fragments/LibraryFragment.kt +++ b/app/phone/src/main/java/dev/jdtech/jellyfin/fragments/LibraryFragment.kt @@ -25,6 +25,7 @@ import dev.jdtech.jellyfin.databinding.FragmentLibraryBinding import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment import dev.jdtech.jellyfin.dialogs.SortDialogFragment import dev.jdtech.jellyfin.models.FindroidBoxSet +import dev.jdtech.jellyfin.models.FindroidFolder import dev.jdtech.jellyfin.models.FindroidItem import dev.jdtech.jellyfin.models.FindroidMovie import dev.jdtech.jellyfin.models.FindroidShow @@ -222,6 +223,15 @@ class LibraryFragment : Fragment() { ), ) } + is FindroidFolder -> { + findNavController().navigate( + LibraryFragmentDirections.actionLibraryFragmentSelf( + item.id, + item.name, + args.libraryType, + ), + ) + } } } } diff --git a/app/phone/src/main/res/navigation/app_navigation.xml b/app/phone/src/main/res/navigation/app_navigation.xml index cf534870..6051dec7 100644 --- a/app/phone/src/main/res/navigation/app_navigation.xml +++ b/app/phone/src/main/res/navigation/app_navigation.xml @@ -123,6 +123,9 @@ + { navigator.navigate(ShowScreenDestination(item.id)) } + is FindroidFolder -> { + navigator.navigate(LibraryScreenDestination(item.id, item.name, libraryType)) + } } }, ) diff --git a/core/src/main/java/dev/jdtech/jellyfin/viewmodels/HomeViewModel.kt b/core/src/main/java/dev/jdtech/jellyfin/viewmodels/HomeViewModel.kt index 5802cb16..0a5044bd 100644 --- a/core/src/main/java/dev/jdtech/jellyfin/viewmodels/HomeViewModel.kt +++ b/core/src/main/java/dev/jdtech/jellyfin/viewmodels/HomeViewModel.kt @@ -93,7 +93,7 @@ class HomeViewModel @Inject internal constructor( private suspend fun loadViews() = repository .getUserViews() - .filter { view -> CollectionType.supported.any { it.type == view.collectionType } } + .filter { view -> CollectionType.fromString(view.collectionType) in CollectionType.supported } .map { view -> view to repository.getLatestMedia(view.id) } .filter { (_, latest) -> latest.isNotEmpty() } .map { (view, latest) -> view.toView().apply { items = latest } } diff --git a/core/src/main/java/dev/jdtech/jellyfin/viewmodels/LibraryViewModel.kt b/core/src/main/java/dev/jdtech/jellyfin/viewmodels/LibraryViewModel.kt index 3ccc04e0..b44950f8 100644 --- a/core/src/main/java/dev/jdtech/jellyfin/viewmodels/LibraryViewModel.kt +++ b/core/src/main/java/dev/jdtech/jellyfin/viewmodels/LibraryViewModel.kt @@ -48,15 +48,19 @@ constructor( CollectionType.Movies -> listOf(BaseItemKind.MOVIE) CollectionType.TvShows -> listOf(BaseItemKind.SERIES) CollectionType.BoxSets -> listOf(BaseItemKind.BOX_SET) + CollectionType.Mixed -> listOf(BaseItemKind.FOLDER, BaseItemKind.MOVIE, BaseItemKind.SERIES) else -> null } + + val recursive = itemType == null || !itemType.contains(BaseItemKind.FOLDER) + viewModelScope.launch { _uiState.emit(UiState.Loading) try { val items = jellyfinRepository.getItemsPaging( parentId = parentId, includeTypes = itemType, - recursive = true, + recursive = recursive, sortBy = sortBy, sortOrder = sortOrder, ).cachedIn(viewModelScope) diff --git a/data/src/main/java/dev/jdtech/jellyfin/models/CollectionType.kt b/data/src/main/java/dev/jdtech/jellyfin/models/CollectionType.kt index e8922df7..8217fbdf 100644 --- a/data/src/main/java/dev/jdtech/jellyfin/models/CollectionType.kt +++ b/data/src/main/java/dev/jdtech/jellyfin/models/CollectionType.kt @@ -9,6 +9,7 @@ enum class CollectionType(val type: String) { Books("books"), LiveTv("livetv"), BoxSets("boxsets"), + Mixed("null"), Unknown("unknown"), ; @@ -19,11 +20,12 @@ enum class CollectionType(val type: String) { Movies, TvShows, BoxSets, + Mixed, ) fun fromString(string: String?): CollectionType { - if (string == null) { - return defaultValue + if (string == null) { // TODO jellyfin returns null as the collectiontype for mixed libraries. This is obviously wrong, but probably an upstream issue. Should be fixed whenever upstream fixes this + return Mixed } return try { diff --git a/data/src/main/java/dev/jdtech/jellyfin/models/FindroidFolder.kt b/data/src/main/java/dev/jdtech/jellyfin/models/FindroidFolder.kt new file mode 100644 index 00000000..dc310a03 --- /dev/null +++ b/data/src/main/java/dev/jdtech/jellyfin/models/FindroidFolder.kt @@ -0,0 +1,35 @@ +package dev.jdtech.jellyfin.models + +import dev.jdtech.jellyfin.repository.JellyfinRepository +import org.jellyfin.sdk.model.api.BaseItemDto +import java.util.UUID + +data class FindroidFolder( + override val id: UUID, + override val name: String, + override val originalTitle: String? = null, + override val overview: String = "", + override val played: Boolean, + override val favorite: Boolean, + override val canPlay: Boolean = false, + override val canDownload: Boolean = false, + override val sources: List = emptyList(), + override val runtimeTicks: Long = 0L, + override val playbackPositionTicks: Long = 0L, + override val unplayedItemCount: Int?, + override val images: FindroidImages, + override val chapters: List? = null, +) : FindroidItem + +fun BaseItemDto.toFindroidFolder( + jellyfinRepository: JellyfinRepository, +): FindroidFolder { + return FindroidFolder( + id = id, + name = name.orEmpty(), + played = userData?.played ?: false, + favorite = userData?.isFavorite ?: false, + unplayedItemCount = userData?.unplayedItemCount, + images = toFindroidImages(jellyfinRepository), + ) +} diff --git a/data/src/main/java/dev/jdtech/jellyfin/models/FindroidItem.kt b/data/src/main/java/dev/jdtech/jellyfin/models/FindroidItem.kt index 2cdabe04..6ce0b867 100644 --- a/data/src/main/java/dev/jdtech/jellyfin/models/FindroidItem.kt +++ b/data/src/main/java/dev/jdtech/jellyfin/models/FindroidItem.kt @@ -33,6 +33,7 @@ suspend fun BaseItemDto.toFindroidItem( BaseItemKind.SEASON -> toFindroidSeason(jellyfinRepository) BaseItemKind.SERIES -> toFindroidShow(jellyfinRepository) BaseItemKind.BOX_SET -> toFindroidBoxSet(jellyfinRepository) + BaseItemKind.FOLDER -> toFindroidFolder(jellyfinRepository) else -> null } }