Fix Folder Libraries (#555)

This commit is contained in:
Ethan Pippin 2022-09-03 23:19:45 -06:00 committed by GitHub
parent 14f1219500
commit 2a3617bd47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 78 additions and 39 deletions

View File

@ -48,6 +48,8 @@ final class LibraryCoordinator: NavigationCoordinatable {
var item = makeItem
@Route(.modal)
var filter = makeFilter
@Route(.push)
var library = makeLibrary
#endif
private let parameters: Parameters
@ -77,5 +79,9 @@ final class LibraryCoordinator: NavigationCoordinatable {
func makeFilter(parameters: FilterCoordinator.Parameters) -> NavigationViewCoordinator<FilterCoordinator> {
NavigationViewCoordinator(FilterCoordinator(parameters: parameters))
}
func makeLibrary(parameters: LibraryCoordinator.Parameters) -> LibraryCoordinator {
LibraryCoordinator(parameters: parameters)
}
#endif
}

View File

@ -86,26 +86,26 @@ final class LibraryViewModel: ViewModel {
}
}
var recursive = true
let includeItemTypes: [BaseItemKind]
if filters.filters.contains(ItemFilter.isFavorite.filter) {
includeItemTypes = [.movie, .boxSet, .series, .season, .episode]
} else if type == .folders {
includeItemTypes = [.collectionFolder]
recursive = false
includeItemTypes = [.movie, .boxSet, .series, .folder, .collectionFolder]
} else {
includeItemTypes = [.movie, .series, .boxSet]
includeItemTypes = [.movie, .boxSet, .series]
}
let excludedIDs: [String]?
var excludedIDs: [String]?
if filters.sortBy.first == SortBy.random.filter {
excludedIDs = items.compactMap(\.id)
} else {
excludedIDs = nil
}
let genreIDs = filters.genres.compactMap(\.id)
let sortBy: [String] = filters.sortBy.map(\.filterName)
let sortBy: [String] = filters.sortBy.map(\.filterName).appending("IsFolder")
let sortOrder = filters.sortOrder.map { SortOrder(rawValue: $0.filterName) ?? .ascending }
let itemFilters: [ItemFilter] = filters.filters.compactMap { .init(rawValue: $0.filterName) }
let tags: [String] = filters.tags.map(\.filterName)
@ -115,7 +115,7 @@ final class LibraryViewModel: ViewModel {
excludeItemIds: excludedIDs,
startIndex: currentPage * pageItemSize,
limit: pageItemSize,
recursive: true,
recursive: recursive,
sortOrder: sortOrder,
parentId: libraryID,
fields: ItemFields.allCases,

View File

@ -14,10 +14,10 @@ struct PosterButton<Item: Poster, Content: View, ImageOverlay: View, ContextMenu
private var type: PosterType
private var itemScale: CGFloat
private var horizontalAlignment: HorizontalAlignment
private var content: (Item) -> Content
private var imageOverlay: (Item) -> ImageOverlay
private var contextMenu: (Item) -> ContextMenu
private var onSelect: (Item) -> Void
private var content: () -> Content
private var imageOverlay: () -> ImageOverlay
private var contextMenu: () -> ContextMenu
private var onSelect: () -> Void
private var singleImage: Bool
private var itemWidth: CGFloat {
@ -29,10 +29,10 @@ struct PosterButton<Item: Poster, Content: View, ImageOverlay: View, ContextMenu
type: PosterType,
itemScale: CGFloat,
horizontalAlignment: HorizontalAlignment,
@ViewBuilder content: @escaping (Item) -> Content,
@ViewBuilder imageOverlay: @escaping (Item) -> ImageOverlay,
@ViewBuilder contextMenu: @escaping (Item) -> ContextMenu,
onSelect: @escaping (Item) -> Void,
@ViewBuilder content: @escaping () -> Content,
@ViewBuilder imageOverlay: @escaping () -> ImageOverlay,
@ViewBuilder contextMenu: @escaping () -> ContextMenu,
onSelect: @escaping () -> Void,
singleImage: Bool
) {
self.item = item
@ -49,7 +49,7 @@ struct PosterButton<Item: Poster, Content: View, ImageOverlay: View, ContextMenu
var body: some View {
VStack(alignment: horizontalAlignment) {
Button {
onSelect(item)
onSelect()
} label: {
Group {
switch type {
@ -60,17 +60,17 @@ struct PosterButton<Item: Poster, Content: View, ImageOverlay: View, ContextMenu
}
}
.overlay {
imageOverlay(item)
imageOverlay()
.posterStyle(type: type, width: itemWidth)
}
}
.contextMenu(menuItems: {
contextMenu(item)
contextMenu()
})
.posterStyle(type: type, width: itemWidth)
.posterShadow()
content(item)
content()
}
.frame(width: itemWidth)
}
@ -86,10 +86,10 @@ extension PosterButton where Content == PosterButtonDefaultContentView<Item>,
type: type,
itemScale: 1,
horizontalAlignment: .leading,
content: { PosterButtonDefaultContentView(item: $0) },
imageOverlay: { _ in EmptyView() },
contextMenu: { _ in EmptyView() },
onSelect: { _ in },
content: { PosterButtonDefaultContentView(item: item) },
imageOverlay: { EmptyView() },
contextMenu: { EmptyView() },
onSelect: {},
singleImage: singleImage
)
}
@ -109,7 +109,7 @@ extension PosterButton {
}
@ViewBuilder
func content<C: View>(@ViewBuilder _ content: @escaping (Item) -> C) -> PosterButton<Item, C, ImageOverlay, ContextMenu> {
func content<C: View>(@ViewBuilder _ content: @escaping () -> C) -> PosterButton<Item, C, ImageOverlay, ContextMenu> {
PosterButton<Item, C, ImageOverlay, ContextMenu>(
item: item,
type: type,
@ -124,7 +124,7 @@ extension PosterButton {
}
@ViewBuilder
func imageOverlay<O: View>(@ViewBuilder _ imageOverlay: @escaping (Item) -> O) -> PosterButton<Item, Content, O, ContextMenu> {
func imageOverlay<O: View>(@ViewBuilder _ imageOverlay: @escaping () -> O) -> PosterButton<Item, Content, O, ContextMenu> {
PosterButton<Item, Content, O, ContextMenu>(
item: item,
type: type,
@ -139,7 +139,7 @@ extension PosterButton {
}
@ViewBuilder
func contextMenu<M: View>(@ViewBuilder _ contextMenu: @escaping (Item) -> M) -> PosterButton<Item, Content, ImageOverlay, M> {
func contextMenu<M: View>(@ViewBuilder _ contextMenu: @escaping () -> M) -> PosterButton<Item, Content, ImageOverlay, M> {
PosterButton<Item, Content, ImageOverlay, M>(
item: item,
type: type,
@ -153,7 +153,7 @@ extension PosterButton {
)
}
func onSelect(_ action: @escaping (Item) -> Void) -> Self {
func onSelect(_ action: @escaping () -> Void) -> Self {
var copy = self
copy.onSelect = action
return copy

View File

@ -65,9 +65,9 @@ struct PosterHStack<Item: Poster, Content: View, ImageOverlay: View, ContextMenu
ForEach(items, id: \.hashValue) { item in
PosterButton(item: item, type: type)
.scaleItem(itemScale)
.imageOverlay(imageOverlay)
.contextMenu(contextMenu)
.onSelect(onSelect)
.imageOverlay { imageOverlay(item) }
.contextMenu { contextMenu(item) }
.onSelect { onSelect(item) }
}
}
.padding(.horizontal)

View File

@ -22,7 +22,7 @@ struct EpisodeCard<RowManager: EpisodesRowManager>: View {
var body: some View {
PosterButton(item: episode, type: .landscape, singleImage: true)
.scaleItem(1.2)
.imageOverlay { _ in
.imageOverlay {
if let progress = episode.progress {
LandscapePosterProgressBar(
title: progress,
@ -40,7 +40,7 @@ struct EpisodeCard<RowManager: EpisodesRowManager>: View {
}
}
}
.content { _ in
.content {
Button {
router.route(to: \.item, episode)
} label: {
@ -78,7 +78,7 @@ struct EpisodeCard<RowManager: EpisodesRowManager>: View {
}
}
}
.onSelect { _ in
.onSelect {
episode.createVideoPlayerViewModel()
.sink { completion in
self.viewModel.handleAPIRequestError(completion: completion)

View File

@ -45,7 +45,8 @@ struct ItemView: View {
case .person:
LibraryView(viewModel: .init(parent: item, type: .person))
case .collectionFolder:
LibraryView(viewModel: .init(parent: item, type: .folders))
Text("Here")
// LibraryView(viewModel: .init(parent: item, type: .folders))
default:
Text(L10n.notImplementedYetWithType(item.type ?? "--"))
}

View File

@ -15,10 +15,11 @@ struct LibraryItemRow: View {
private var router: LibraryCoordinator.Router
let item: BaseItemDto
private var onSelect: () -> Void
var body: some View {
Button {
router.route(to: \.item, item)
onSelect()
} label: {
HStack(alignment: .bottom) {
ImageView(item.portraitPosterImageSource(maxWidth: 60))
@ -55,3 +56,16 @@ struct LibraryItemRow: View {
}
}
}
extension LibraryItemRow {
init(item: BaseItemDto) {
self.item = item
self.onSelect = {}
}
func onSelect(_ action: @escaping () -> Void) -> Self {
var copy = self
copy.onSelect = action
return copy
}
}

View File

@ -8,6 +8,7 @@
import CollectionView
import Defaults
import JellyfinAPI
import SwiftUI
struct LibraryView: View {
@ -40,10 +41,27 @@ struct LibraryView: View {
}
}
private func baseItemOnSelect(_ item: BaseItemDto) {
if let baseParent = viewModel.parent as? BaseItemDto {
if baseParent.collectionType == "folders" {
router.route(to: \.library, .init(parent: item, type: .folders, filters: .init()))
} else if item.type == .folder {
router.route(to: \.library, .init(parent: item, type: .library, filters: .init()))
} else {
router.route(to: \.item, item)
}
} else {
router.route(to: \.item, item)
}
}
@ViewBuilder
private var libraryListView: some View {
CollectionView(items: viewModel.items) { _, item, _ in
LibraryItemRow(item: item)
.onSelect {
baseItemOnSelect(item)
}
.padding()
}
.layout { _, layoutEnvironment in
@ -65,8 +83,8 @@ struct LibraryView: View {
CollectionView(items: viewModel.items) { _, item, _ in
PosterButton(item: item, type: libraryGridPosterType)
.scaleItem(libraryGridPosterType == .landscape && UIDevice.isPhone ? 0.85 : 1)
.onSelect { item in
router.route(to: \.item, item)
.onSelect {
baseItemOnSelect(item)
}
}
.layout { _, layoutEnvironment in

View File

@ -30,7 +30,7 @@ struct MediaView: View {
CollectionView(items: viewModel.libraryItems) { _, item, _ in
PosterButton(item: item, type: .landscape)
.scaleItem(UIDevice.isPhone ? 0.85 : 1)
.onSelect { _ in
.onSelect {
switch item.library.collectionType {
case "favorites":
router.route(to: \.library, .init(parent: item.library, type: .library, filters: .favorites))
@ -42,7 +42,7 @@ struct MediaView: View {
router.route(to: \.library, .init(parent: item.library, type: .library, filters: .init()))
}
}
.imageOverlay { _ in
.imageOverlay {
ZStack {
Color.black
.opacity(0.5)