mirror of
https://github.com/yattee/yattee.git
synced 2025-11-20 08:52:20 +00:00
Reduced video cell and grid item sizes on tvOS to improve layout spacing and visual consistency. Changed grid item size from 600 to 560 pixels, and adjusted video cell frame dimensions accordingly.
116 lines
3.4 KiB
Swift
116 lines
3.4 KiB
Swift
import Defaults
|
|
import SwiftUI
|
|
|
|
struct VerticalCells<Header: View>: View {
|
|
#if os(iOS)
|
|
@Environment(\.verticalSizeClass) private var verticalSizeClass
|
|
#endif
|
|
|
|
@Environment(\.loadMoreContentHandler) private var loadMoreContentHandler
|
|
@Environment(\.listingStyle) private var listingStyle
|
|
@Environment(\.navigationStyle) private var navigationStyle
|
|
|
|
var items = [ContentItem]()
|
|
var allowEmpty = false
|
|
var edgesIgnoringSafeArea = Edge.Set.horizontal
|
|
|
|
let header: Header?
|
|
|
|
@State private var gridSize = CGSize.zero
|
|
|
|
init(
|
|
items: [ContentItem],
|
|
allowEmpty: Bool = false,
|
|
edgesIgnoringSafeArea: Edge.Set = .horizontal,
|
|
@ViewBuilder header: @escaping () -> Header? = { nil }
|
|
) {
|
|
self.items = items
|
|
self.allowEmpty = allowEmpty
|
|
self.edgesIgnoringSafeArea = edgesIgnoringSafeArea
|
|
self.header = header()
|
|
}
|
|
|
|
init(
|
|
items: [ContentItem],
|
|
allowEmpty: Bool = false
|
|
) where Header == EmptyView {
|
|
self.init(items: items, allowEmpty: allowEmpty) { EmptyView() }
|
|
}
|
|
|
|
var body: some View {
|
|
ScrollView(.vertical, showsIndicators: scrollViewShowsIndicators) {
|
|
LazyVGrid(columns: adaptiveItem, alignment: .center) {
|
|
Section(header: header) {
|
|
ForEach(contentItems) { item in
|
|
ContentItemView(item: item)
|
|
.onAppear { loadMoreContentItemsIfNeeded(current: item) }
|
|
}
|
|
}
|
|
}
|
|
.padding()
|
|
}
|
|
.animation(nil)
|
|
#if os(iOS)
|
|
.edgesIgnoringSafeArea(navigationStyle == .sidebar ? [] : edgesIgnoringSafeArea)
|
|
#endif
|
|
#if os(macOS)
|
|
.background(Color.secondaryBackground)
|
|
.frame(minWidth: Constants.contentViewMinWidth)
|
|
#endif
|
|
}
|
|
|
|
var contentItems: [ContentItem] {
|
|
// Avoid sorting on every redraw - items should already be sorted from the source
|
|
// If sorting is truly needed, it should be done once in the model, not in the view
|
|
items.isEmpty ? (allowEmpty ? items : ContentItem.placeholders) : items
|
|
}
|
|
|
|
func loadMoreContentItemsIfNeeded(current item: ContentItem) {
|
|
let thresholdIndex = items.index(items.endIndex, offsetBy: -5)
|
|
if items.firstIndex(where: { $0.id == item.id }) == thresholdIndex {
|
|
loadMoreContentHandler()
|
|
}
|
|
}
|
|
|
|
var adaptiveItem: [GridItem] {
|
|
if listingStyle == .list {
|
|
return [.init(.flexible())]
|
|
}
|
|
|
|
return [GridItem(.adaptive(minimum: adaptiveGridItemMinimumSize, maximum: adaptiveGridItemMaximumSize))]
|
|
}
|
|
|
|
var adaptiveGridItemMinimumSize: Double {
|
|
#if os(iOS)
|
|
return verticalSizeClass == .regular ? 320 : 800
|
|
#elseif os(tvOS)
|
|
return 560
|
|
#else
|
|
return 320
|
|
#endif
|
|
}
|
|
|
|
var adaptiveGridItemMaximumSize: Double {
|
|
#if os(tvOS)
|
|
return 560
|
|
#else
|
|
return .infinity
|
|
#endif
|
|
}
|
|
|
|
var scrollViewShowsIndicators: Bool {
|
|
#if !os(tvOS)
|
|
true
|
|
#else
|
|
false
|
|
#endif
|
|
}
|
|
}
|
|
|
|
struct VeticalCells_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
VerticalCells(items: ContentItem.array(of: Array(repeating: Video.fixture, count: 30)))
|
|
.injectFixtureEnvironmentObjects()
|
|
}
|
|
}
|