use CollectionView on LibraryView

This commit is contained in:
jhays 2021-10-14 09:59:35 -05:00
parent c3b2fadf91
commit 1c2b1879b4
4 changed files with 152 additions and 50 deletions

View File

@ -7,57 +7,95 @@
*/
import SwiftUI
import SwiftUICollection
import JellyfinAPI
struct LibraryView: View {
@StateObject var viewModel: LibraryViewModel
var title: String
@StateObject var viewModel: LibraryViewModel
var title: String
// MARK: tracks for grid
var defaultFilters = LibraryFilters(filters: [], sortOrder: [.ascending], withGenres: [], tags: [], sortBy: [.name])
// MARK: tracks for grid
var defaultFilters = LibraryFilters(filters: [], sortOrder: [.ascending], withGenres: [], tags: [], sortBy: [.name])
@State var isShowingSearchView = false
@State var isShowingFilterView = false
@State private var tracks: [GridItem] = Array(repeating: .init(.flexible()), count: Int(UIScreen.main.bounds.size.width) / 250)
var body: some View {
Group {
if viewModel.isLoading == true {
ProgressView()
} else if !viewModel.items.isEmpty {
ScrollView(.vertical) {
LazyVGrid(columns: tracks) {
ForEach(viewModel.items, id: \.id) { item in
if item.type != "Folder" {
NavigationLink(destination: LazyView { ItemView(item: item) }) {
PortraitItemElement(item: item)
}.buttonStyle(PlainNavigationLinkButtonStyle())
.onAppear {
if item == viewModel.items.last && viewModel.hasNextPage {
print("Last item visible, load more items.")
viewModel.requestNextPageAsync()
}
}
}
}
}.padding()
}
} else {
Text("No results.")
}
}
/*
.sheet(isPresented: $isShowingFilterView) {
LibraryFilterView(filters: $viewModel.filters, enabledFilterType: viewModel.enabledFilterType, parentId: viewModel.parentID ?? "")
}
.background(
NavigationLink(destination: LibrarySearchView(viewModel: .init(parentID: viewModel.parentID)),
isActive: $isShowingSearchView) {
EmptyView()
}
@State var isShowingSearchView = false
@State var isShowingFilterView = false
var body: some View {
if viewModel.isLoading == true {
ProgressView()
} else if !viewModel.items.isEmpty {
CollectionView(rows: viewModel.rows) { _, _ in
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1),
heightDimension: .fractionalHeight(1)
)
*/
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(
widthDimension: .absolute(200),
heightDimension: .absolute(300)
)
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: groupSize,
subitems: [item]
)
let header =
NSCollectionLayoutBoundarySupplementaryItem(
layoutSize: NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1),
heightDimension: .absolute(44)
),
elementKind: UICollectionView.elementKindSectionHeader,
alignment: .topLeading
)
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(top: 30, leading: 0, bottom: 80, trailing: 80)
section.interGroupSpacing = 48
section.orthogonalScrollingBehavior = .continuous
section.boundarySupplementaryItems = [header]
return section
} cell: { _, item in
GeometryReader { _ in
if item.type != "Folder" {
NavigationLink(destination: LazyView { ItemView(item: item) }) {
PortraitItemElement(item: item)
}
.buttonStyle(PlainNavigationLinkButtonStyle())
.onAppear {
if item == viewModel.items.last && viewModel.hasNextPage {
print("Last item visible, load more items.")
viewModel.requestNextPageAsync()
}
}
}
}
} supplementaryView: { _, indexPath in
HStack {
Text("Supp View")
.font(.title3)
Spacer()
}.accessibilityIdentifier("\(indexPath.section).\(indexPath.row)")
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.ignoresSafeArea(.all)
} else {
Text("No results.")
}
/*
.sheet(isPresented: $isShowingFilterView) {
LibraryFilterView(filters: $viewModel.filters, enabledFilterType: viewModel.enabledFilterType, parentId: viewModel.parentID ?? "")
}
.background(
NavigationLink(destination: LibrarySearchView(viewModel: .init(parentID: viewModel.parentID)),
isActive: $isShowingSearchView) {
EmptyView()
}
)
*/
}
}
// stream BM^S by nicki!

View File

@ -252,6 +252,8 @@
62ECA01826FA685A00E8EBB7 /* DeepLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62ECA01726FA685A00E8EBB7 /* DeepLink.swift */; };
AE8C3159265D6F90008AA076 /* bitrates.json in Resources */ = {isa = PBXBuildFile; fileRef = AE8C3158265D6F90008AA076 /* bitrates.json */; };
C45B29BB26FAC5B600CEF5E0 /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = E173DA5126D04AAF00CC4EB7 /* ColorExtension.swift */; };
C49FB6592717A06300AAEABB /* SwiftUICollection in Frameworks */ = {isa = PBXBuildFile; productRef = C49FB6582717A06300AAEABB /* SwiftUICollection */; };
C4BFD4E527167B63007739E3 /* SwiftUICollection in Frameworks */ = {isa = PBXBuildFile; productRef = C4BFD4E427167B63007739E3 /* SwiftUICollection */; };
C4E5081B2703F82A0045C9AB /* LibraryListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E508172703E8190045C9AB /* LibraryListView.swift */; };
C4E5081D2703F8370045C9AB /* LibrarySearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4E5081C2703F8370045C9AB /* LibrarySearchView.swift */; };
E100720726BDABC100CE3E31 /* MediaPlayButtonRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E100720626BDABC100CE3E31 /* MediaPlayButtonRowView.swift */; };
@ -528,6 +530,7 @@
53272535268BF9710035FBF1 /* SwiftUIFocusGuide in Frameworks */,
5358708D2669D7A800D05A09 /* KeychainSwift in Frameworks */,
536D3D84267BEA550004248C /* ParallaxView in Frameworks */,
C49FB6592717A06300AAEABB /* SwiftUICollection in Frameworks */,
53ABFDDC267972BF00886593 /* TVServices.framework in Frameworks */,
5358709B2669D7A800D05A09 /* NukeUI in Frameworks */,
53ABFDED26799D7700886593 /* ActivityIndicator in Frameworks */,
@ -542,6 +545,7 @@
62C29E9C26D0FE4200C1D2E7 /* Stinsen in Frameworks */,
62CB3F462685BAF7003D0A6F /* Defaults in Frameworks */,
5338F757263B7E2E0014BF09 /* KeychainSwift in Frameworks */,
C4BFD4E527167B63007739E3 /* SwiftUICollection in Frameworks */,
53EC6E25267EB10F006DD26A /* SwiftyJSON in Frameworks */,
53EC6E21267E80B1006DD26A /* Pods_JellyfinPlayer_iOS.framework in Frameworks */,
53352571265EA0A0006CCA86 /* Introspect in Frameworks */,
@ -1151,6 +1155,7 @@
53649AAE269CFAF600A2D8B7 /* Puppy */,
6261A0DF26A0AB710072EF1C /* CombineExt */,
6220D0C826D63F3700B8E046 /* Stinsen */,
C49FB6582717A06300AAEABB /* SwiftUICollection */,
);
productName = "JellyfinPlayer tvOS";
productReference = 535870602669D21600D05A09 /* JellyfinPlayer tvOS.app */;
@ -1186,6 +1191,7 @@
53649AAC269CFAEA00A2D8B7 /* Puppy */,
6260FFF826A09754003FA968 /* CombineExt */,
62C29E9B26D0FE4200C1D2E7 /* Stinsen */,
C4BFD4E427167B63007739E3 /* SwiftUICollection */,
);
productName = JellyfinPlayer;
productReference = 5377CBF1263B596A003A4E83 /* JellyfinPlayer iOS.app */;
@ -1275,6 +1281,7 @@
53649AAB269CFAEA00A2D8B7 /* XCRemoteSwiftPackageReference "Puppy" */,
6260FFF726A09754003FA968 /* XCRemoteSwiftPackageReference "CombineExt" */,
62C29E9A26D0FE4100C1D2E7 /* XCRemoteSwiftPackageReference "stinsen" */,
C4BFD4E327167B63007739E3 /* XCRemoteSwiftPackageReference "SwiftUICollection" */,
);
productRefGroup = 5377CBF2263B596A003A4E83 /* Products */;
projectDirPath = "";
@ -2268,6 +2275,14 @@
kind = branch;
};
};
C4BFD4E327167B63007739E3 /* XCRemoteSwiftPackageReference "SwiftUICollection" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/ABJC/SwiftUICollection";
requirement = {
branch = master;
kind = branch;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
@ -2406,6 +2421,16 @@
package = 62CB3F442685BAF7003D0A6F /* XCRemoteSwiftPackageReference "Defaults" */;
productName = Defaults;
};
C49FB6582717A06300AAEABB /* SwiftUICollection */ = {
isa = XCSwiftPackageProductDependency;
package = C4BFD4E327167B63007739E3 /* XCRemoteSwiftPackageReference "SwiftUICollection" */;
productName = SwiftUICollection;
};
C4BFD4E427167B63007739E3 /* SwiftUICollection */ = {
isa = XCSwiftPackageProductDependency;
package = C4BFD4E327167B63007739E3 /* XCRemoteSwiftPackageReference "SwiftUICollection" */;
productName = SwiftUICollection;
};
/* End XCSwiftPackageProductDependency section */
/* Begin XCVersionGroup section */

View File

@ -136,6 +136,15 @@
"version": "0.1.3"
}
},
{
"package": "SwiftUICollection",
"repositoryURL": "https://github.com/ABJC/SwiftUICollection",
"state": {
"branch": "master",
"revision": "e27149382ce8ec21995069c8aab7ca83d61a3120",
"version": null
}
},
{
"package": "SwiftUIFocusGuide",
"repositoryURL": "https://github.com/rmnblm/SwiftUIFocusGuide",

View File

@ -10,6 +10,9 @@
import Combine
import Foundation
import JellyfinAPI
import SwiftUICollection
typealias LibraryRow = CollectionRow<Int, BaseItemDto>
final class LibraryViewModel: ViewModel {
var parentID: String?
@ -18,6 +21,7 @@ final class LibraryViewModel: ViewModel {
var studio: NameGuidPair?
@Published var items = [BaseItemDto]()
@Published var rows = [LibraryRow]()
@Published var totalPages = 0
@Published var currentPage = 0
@ -26,6 +30,8 @@ final class LibraryViewModel: ViewModel {
// temp
@Published var filters: LibraryFilters
private let columns: Int
var enabledFilterType: [FilterType] {
if genre == nil {
@ -35,16 +41,20 @@ final class LibraryViewModel: ViewModel {
}
}
init(parentID: String? = nil,
person: BaseItemPerson? = nil,
genre: NameGuidPair? = nil,
studio: NameGuidPair? = nil,
filters: LibraryFilters = LibraryFilters(filters: [], sortOrder: [.ascending], withGenres: [], sortBy: [.name])) {
init(
parentID: String? = nil,
person: BaseItemPerson? = nil,
genre: NameGuidPair? = nil,
studio: NameGuidPair? = nil,
filters: LibraryFilters = LibraryFilters(filters: [], sortOrder: [.ascending], withGenres: [], sortBy: [.name]),
columns: Int = 7
) {
self.parentID = parentID
self.person = person
self.genre = genre
self.studio = studio
self.filters = filters
self.columns = columns
super.init()
$filters
@ -79,6 +89,7 @@ final class LibraryViewModel: ViewModel {
self.hasPreviousPage = self.currentPage > 0
self.hasNextPage = self.currentPage < self.totalPages - 1
self.items = response.items ?? []
self.calculateRows()
})
.store(in: &cancellables)
}
@ -108,6 +119,7 @@ final class LibraryViewModel: ViewModel {
self.hasPreviousPage = self.currentPage > 0
self.hasNextPage = self.currentPage < self.totalPages - 1
self.items.append(contentsOf: response.items ?? [])
self.calculateRows()
})
.store(in: &cancellables)
}
@ -126,4 +138,22 @@ final class LibraryViewModel: ViewModel {
currentPage -= 1
requestItems(with: filters)
}
private func calculateRows() {
let rowCount = items.count / columns
rows = [LibraryRow]()
for i in (0...rowCount) {
let firstItemIndex = i * columns
var lastItemIndex = firstItemIndex + columns
if lastItemIndex >= items.count {
lastItemIndex = items.count - 1
}
rows.append(
LibraryRow(
section: i,
items: Array(items[firstItemIndex...lastItemIndex])
)
)
}
}
}