mirror of
https://github.com/yattee/yattee.git
synced 2026-02-20 01:39:46 +00:00
Yattee v2 rewrite
This commit is contained in:
133
Yattee/Models/VideoListLayout.swift
Normal file
133
Yattee/Models/VideoListLayout.swift
Normal file
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// VideoListLayout.swift
|
||||
// Yattee
|
||||
//
|
||||
// Layout options for video listing views.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
/// Layout type for video lists.
|
||||
enum VideoListLayout: String, CaseIterable {
|
||||
case list
|
||||
case grid
|
||||
|
||||
var displayName: LocalizedStringKey {
|
||||
switch self {
|
||||
case .list: "viewOptions.layout.list"
|
||||
case .grid: "viewOptions.layout.grid"
|
||||
}
|
||||
}
|
||||
|
||||
var systemImage: String {
|
||||
switch self {
|
||||
case .list: "list.bullet"
|
||||
case .grid: "square.grid.2x2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Grid Layout Helpers
|
||||
|
||||
/// Constants for grid layout calculations.
|
||||
enum GridConstants {
|
||||
/// Minimum width for a video card thumbnail to remain usable.
|
||||
static let minCardWidth: CGFloat = {
|
||||
#if os(tvOS)
|
||||
200
|
||||
#else
|
||||
100
|
||||
#endif
|
||||
}()
|
||||
|
||||
/// Spacing between grid items.
|
||||
static let spacing: CGFloat = {
|
||||
#if os(tvOS)
|
||||
32
|
||||
#else
|
||||
12
|
||||
#endif
|
||||
}()
|
||||
|
||||
/// Horizontal padding for the grid container.
|
||||
static let horizontalPadding: CGFloat = 32
|
||||
|
||||
/// Maximum allowed columns (to prevent excessive density).
|
||||
static let maxAllowedColumns = 6
|
||||
|
||||
/// Threshold for compact card styling (columns >= this use compact mode).
|
||||
static let compactThreshold = 3
|
||||
}
|
||||
|
||||
/// Calculates the maximum number of grid columns that fit within a given width.
|
||||
/// - Parameters:
|
||||
/// - width: Available container width
|
||||
/// - minCardWidth: Minimum width per card (defaults to GridConstants.minCardWidth)
|
||||
/// - spacing: Spacing between cards (defaults to GridConstants.spacing)
|
||||
/// - Returns: Maximum columns that fit, clamped between 1 and maxAllowedColumns
|
||||
func maxGridColumns(
|
||||
forWidth width: CGFloat,
|
||||
minCardWidth: CGFloat = GridConstants.minCardWidth,
|
||||
spacing: CGFloat = GridConstants.spacing
|
||||
) -> Int {
|
||||
let availableWidth = width - GridConstants.horizontalPadding
|
||||
// Formula: availableWidth = (columns * minCardWidth) + ((columns - 1) * spacing)
|
||||
// Solving for columns: columns = (availableWidth + spacing) / (minCardWidth + spacing)
|
||||
let maxColumns = Int((availableWidth + spacing) / (minCardWidth + spacing))
|
||||
return max(1, min(maxColumns, GridConstants.maxAllowedColumns))
|
||||
}
|
||||
|
||||
/// Creates grid columns for a LazyVGrid with the specified count.
|
||||
/// - Parameter count: Number of columns
|
||||
/// - Returns: Array of flexible GridItems with top alignment
|
||||
func makeGridColumns(count: Int) -> [GridItem] {
|
||||
Array(repeating: GridItem(.flexible(), spacing: GridConstants.spacing, alignment: .top), count: max(1, count))
|
||||
}
|
||||
|
||||
// MARK: - Grid Layout Configuration
|
||||
|
||||
/// Encapsulates grid layout calculations for views with grid/list layouts.
|
||||
///
|
||||
/// Use this to eliminate repeated computed properties across grid-enabled views.
|
||||
/// Create an instance with the current view width and user-selected column count,
|
||||
/// then use the computed properties for layout decisions.
|
||||
///
|
||||
/// Usage:
|
||||
/// ```swift
|
||||
/// @State private var viewWidth: CGFloat = 0
|
||||
/// @AppStorage("myView.gridColumns") private var gridColumns = 2
|
||||
///
|
||||
/// private var gridConfig: GridLayoutConfiguration {
|
||||
/// GridLayoutConfiguration(viewWidth: viewWidth, gridColumns: gridColumns)
|
||||
/// }
|
||||
///
|
||||
/// // Then use:
|
||||
/// // gridConfig.effectiveColumns - actual column count
|
||||
/// // gridConfig.isCompactCards - whether to use compact card styling
|
||||
/// // gridConfig.columns - GridItem array for LazyVGrid
|
||||
/// // gridConfig.maxColumns - for ViewOptionsSheet
|
||||
/// ```
|
||||
struct GridLayoutConfiguration {
|
||||
let viewWidth: CGFloat
|
||||
let gridColumns: Int
|
||||
|
||||
/// Maximum columns that fit in the current width.
|
||||
var maxColumns: Int {
|
||||
maxGridColumns(forWidth: viewWidth)
|
||||
}
|
||||
|
||||
/// Effective column count, clamped to valid range.
|
||||
var effectiveColumns: Int {
|
||||
min(max(1, gridColumns), max(1, maxColumns))
|
||||
}
|
||||
|
||||
/// Whether cards should use compact styling (3+ columns).
|
||||
var isCompactCards: Bool {
|
||||
effectiveColumns >= GridConstants.compactThreshold
|
||||
}
|
||||
|
||||
/// GridItem array for LazyVGrid columns parameter.
|
||||
var columns: [GridItem] {
|
||||
makeGridColumns(count: effectiveColumns)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user