From c1563e52d33c8fe310b7aa86e7f75459ad3ce8d5 Mon Sep 17 00:00:00 2001 From: Quang <43954417+quangDecember@users.noreply.github.com> Date: Tue, 3 Jun 2025 17:42:11 -0400 Subject: [PATCH] Played/Unplayed status for "Collection" and "TV Shows" (#1495) * off recursive * pr feedback * Cleanup Instantiate the collectionType in the `if let` since failure to cast `as? BaseItemDto` should count as false as well. Only set `parameters.isRecursive` once in if/else opposed to if -> override. * wip * fix recursive and item kinds * rename, fix folders --------- Co-authored-by: Quang Co-authored-by: Joe Co-authored-by: Ethan Pippin Co-authored-by: Quang --- .../BaseItemDto+LibraryParent.swift | 41 +++++++++++++++++++ .../JellyfinAPI/BaseItemDto/BaseItemDto.swift | 7 ---- .../ItemLibraryViewModel.swift | 4 +- Swiftfin.xcodeproj/project.pbxproj | 6 +++ 4 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 Shared/Extensions/JellyfinAPI/BaseItemDto/BaseItemDto+LibraryParent.swift diff --git a/Shared/Extensions/JellyfinAPI/BaseItemDto/BaseItemDto+LibraryParent.swift b/Shared/Extensions/JellyfinAPI/BaseItemDto/BaseItemDto+LibraryParent.swift new file mode 100644 index 00000000..c780a81e --- /dev/null +++ b/Shared/Extensions/JellyfinAPI/BaseItemDto/BaseItemDto+LibraryParent.swift @@ -0,0 +1,41 @@ +// +// Swiftfin is subject to the terms of the Mozilla Public +// License, v2.0. If a copy of the MPL was not distributed with this +// file, you can obtain one at https://mozilla.org/MPL/2.0/. +// +// Copyright (c) 2025 Jellyfin & Jellyfin Contributors +// + +import JellyfinAPI + +extension BaseItemDto: LibraryParent { + + var libraryType: BaseItemKind? { + type + } + + var supportedItemTypes: [BaseItemKind] { + guard let collectionType else { return [] } + + switch (collectionType, libraryType) { + case (_, .folder): + return BaseItemKind.supportedCases + .appending([.folder, .collectionFolder]) + case (.movies, _): + return [.movie] + case (.tvshows, _): + return [.series] + case (.boxsets, _): + return BaseItemKind.supportedCases + default: + return BaseItemKind.supportedCases + } + } + + var isRecursiveCollection: Bool { + if let collectionType, [CollectionType.tvshows, CollectionType.boxsets].contains(collectionType) { + return false + } + return true + } +} diff --git a/Shared/Extensions/JellyfinAPI/BaseItemDto/BaseItemDto.swift b/Shared/Extensions/JellyfinAPI/BaseItemDto/BaseItemDto.swift index ab9774ee..efde57fd 100644 --- a/Shared/Extensions/JellyfinAPI/BaseItemDto/BaseItemDto.swift +++ b/Shared/Extensions/JellyfinAPI/BaseItemDto/BaseItemDto.swift @@ -21,13 +21,6 @@ extension BaseItemDto: Displayable { } } -extension BaseItemDto: LibraryParent { - - var libraryType: BaseItemKind? { - type - } -} - extension BaseItemDto: LibraryIdentifiable { var unwrappedIDHashOrZero: Int { diff --git a/Shared/ViewModels/LibraryViewModel/ItemLibraryViewModel.swift b/Shared/ViewModels/LibraryViewModel/ItemLibraryViewModel.swift index 2eace6a6..96a44205 100644 --- a/Shared/ViewModels/LibraryViewModel/ItemLibraryViewModel.swift +++ b/Shared/ViewModels/LibraryViewModel/ItemLibraryViewModel.swift @@ -57,11 +57,13 @@ final class ItemLibraryViewModel: PagingLibraryViewModel { // Default values, expected to be overridden // by parent or filters - parameters.isRecursive = true parameters.includeItemTypes = BaseItemKind.supportedCases parameters.sortOrder = [.ascending] parameters.sortBy = [ItemSortBy.name.rawValue] + /// Recursive should only apply to parents/folders and not to baseItems + parameters.isRecursive = (parent as? BaseItemDto)?.isRecursiveCollection ?? false + // Parent if let parent { parameters = parent.setParentParameters(parameters) diff --git a/Swiftfin.xcodeproj/project.pbxproj b/Swiftfin.xcodeproj/project.pbxproj index d72c65b5..ed8d2963 100644 --- a/Swiftfin.xcodeproj/project.pbxproj +++ b/Swiftfin.xcodeproj/project.pbxproj @@ -757,6 +757,8 @@ E14EDEC92B8FB65F000F00A4 /* ItemFilterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14EDEC72B8FB65F000F00A4 /* ItemFilterType.swift */; }; E14EDECC2B8FB709000F00A4 /* ItemYear.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14EDECB2B8FB709000F00A4 /* ItemYear.swift */; }; E14EDECD2B8FB709000F00A4 /* ItemYear.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14EDECB2B8FB709000F00A4 /* ItemYear.swift */; }; + E14FC7F42DB4436A005F0FB0 /* BaseItemDto+LibraryParent.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14FC7F32DB4436A005F0FB0 /* BaseItemDto+LibraryParent.swift */; }; + E14FC7F52DB4436A005F0FB0 /* BaseItemDto+LibraryParent.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14FC7F32DB4436A005F0FB0 /* BaseItemDto+LibraryParent.swift */; }; E150C0BA2BFD44F500944FFA /* ImagePipeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = E150C0B92BFD44F500944FFA /* ImagePipeline.swift */; }; E150C0BB2BFD44F500944FFA /* ImagePipeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = E150C0B92BFD44F500944FFA /* ImagePipeline.swift */; }; E150C0C12BFD62FD00944FFA /* JellyfinAPI in Frameworks */ = {isa = PBXBuildFile; productRef = E150C0C02BFD62FD00944FFA /* JellyfinAPI */; }; @@ -1834,6 +1836,7 @@ E14EDEC42B8FB64E000F00A4 /* AnyItemFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyItemFilter.swift; sourceTree = ""; }; E14EDEC72B8FB65F000F00A4 /* ItemFilterType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemFilterType.swift; sourceTree = ""; }; E14EDECB2B8FB709000F00A4 /* ItemYear.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemYear.swift; sourceTree = ""; }; + E14FC7F32DB4436A005F0FB0 /* BaseItemDto+LibraryParent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BaseItemDto+LibraryParent.swift"; sourceTree = ""; }; E150C0B92BFD44F500944FFA /* ImagePipeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePipeline.swift; sourceTree = ""; }; E152107B2947ACA000375CC2 /* InvertedLightAppIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvertedLightAppIcon.swift; sourceTree = ""; }; E1546776289AF46E00087E35 /* CollectionItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionItemView.swift; sourceTree = ""; }; @@ -5227,6 +5230,7 @@ children = ( E1AD104C26D96CE3003E4A08 /* BaseItemDto.swift */, E1937A3A288E54AD00CB80AA /* BaseItemDto+Images.swift */, + E14FC7F32DB4436A005F0FB0 /* BaseItemDto+LibraryParent.swift */, E18845F426DD631E00B0C5B7 /* BaseItemDto+Poster.swift */, E18A8E7C28D606BE00333B9A /* BaseItemDto+VideoPlayerViewModel.swift */, ); @@ -5947,6 +5951,7 @@ E102314B2BCF8A6D009D71FC /* ProgramsViewModel.swift in Sources */, E1DD55382B6EE533007501C0 /* Task.swift in Sources */, 4E2CE3942DA432C00004736A /* LogLevel.swift in Sources */, + E14FC7F52DB4436A005F0FB0 /* BaseItemDto+LibraryParent.swift in Sources */, E1575EA1293E7B1E001665B1 /* String.swift in Sources */, 4E699BC02CB3477D007CBD5D /* HomeSection.swift in Sources */, E1E6C45429B1304E0064123F /* ChaptersActionButton.swift in Sources */, @@ -6811,6 +6816,7 @@ E1ED7FDC2CAA4B6D00ACB6E3 /* PlayerStateInfo.swift in Sources */, E149CCAD2BE6ECC8008B9331 /* Storable.swift in Sources */, E1CB75792C80ECF100217C76 /* VideoPlayerType+Native.swift in Sources */, + E14FC7F42DB4436A005F0FB0 /* BaseItemDto+LibraryParent.swift in Sources */, E1401CA72938140300E8B599 /* PrimaryAppIcon.swift in Sources */, E1937A3E288F0D3D00CB80AA /* UIScreen.swift in Sources */, E10B1EBE2BD9AD5C00A92EAF /* V1ServerModel.swift in Sources */,