Features: - VOD library with movie grouping and version detection - TV show library with season/episode organization - TMDB integration for trending shows and recently aired episodes - Recent releases section with TMDB release date sorting - Watch history tracking with continue watching - Playlist caching (12-hour TTL) for offline support - M3U playlist parsing with XStream API support - Authentication with credential storage Technical: - SwiftUI for tvOS - Actor-based services for thread safety - Persistent caching for playlists, TMDB data, and watch history - KSPlayer integration for video playback Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
78 lines
2.1 KiB
Swift
78 lines
2.1 KiB
Swift
//
|
|
// AirPlayView.swift
|
|
// KSPlayer
|
|
//
|
|
// Created by kintan on 2023/5/4.
|
|
//
|
|
|
|
import AVKit
|
|
import SwiftUI
|
|
|
|
#if !os(xrOS)
|
|
public struct AirPlayView: UIViewRepresentable {
|
|
public init() {}
|
|
|
|
#if canImport(UIKit)
|
|
public typealias UIViewType = AVRoutePickerView
|
|
public func makeUIView(context _: Context) -> UIViewType {
|
|
let routePickerView = AVRoutePickerView()
|
|
routePickerView.tintColor = .white
|
|
return routePickerView
|
|
}
|
|
|
|
public func updateUIView(_: UIViewType, context _: Context) {}
|
|
#else
|
|
public typealias NSViewType = AVRoutePickerView
|
|
public func makeNSView(context _: Context) -> NSViewType {
|
|
let routePickerView = AVRoutePickerView()
|
|
routePickerView.isRoutePickerButtonBordered = false
|
|
return routePickerView
|
|
}
|
|
|
|
public func updateNSView(_: NSViewType, context _: Context) {}
|
|
#endif
|
|
}
|
|
#endif
|
|
public extension View {
|
|
/// Applies the given transform if the given condition evaluates to `true`.
|
|
/// - Parameters:
|
|
/// - condition: The condition to evaluate.
|
|
/// - transform: The transform to apply to the source `View`.
|
|
/// - Returns: Either the original `View` or the modified `View` if the condition is `true`.
|
|
@ViewBuilder
|
|
func `if`(_ condition: @autoclosure () -> Bool, transform: (Self) -> some View) -> some View {
|
|
if condition() {
|
|
transform(self)
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
func `if`(_ condition: @autoclosure () -> Bool, if ifTransform: (Self) -> some View, else elseTransform: (Self) -> some View) -> some View {
|
|
if condition() {
|
|
ifTransform(self)
|
|
} else {
|
|
elseTransform(self)
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
func ifLet<T: Any>(_ optionalValue: T?, transform: (Self, T) -> some View) -> some View {
|
|
if let value = optionalValue {
|
|
transform(self, value)
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Bool {
|
|
static var iOS16: Bool {
|
|
guard #available(iOS 16, *) else {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
}
|