Files
yattee/Yattee/Views/Player/Panels/RelatedPanelPage.swift
Arkadiusz Fal c289e7576e Add per-page element customization and panel settings polish
Phase 5 of the player panels redesign:
- Per-page element toggles now rendered and editable for every page:
  comments (author avatars), related (thumbnails), chapters (thumbnails),
  queue (previously played section), tracks (video/audio/subtitles/speed
  sections)
- Page bar labels toggle (icons-only bar shows the selected page's name)
- Layout mode schematic diagram in the details panel settings
- NEW badge machinery for future page types (versionAdded on PanelPageType)
- Typed per-page settings accessors on PanelPageConfiguration and VM update
  helpers for each page kind
- Unit tests for per-page settings round-trip and accessor fallbacks

The standalone quality selector sheet is unaffected: section gating defaults
to everything visible and only the embedded tracks page passes preset
settings through.
2026-09-22 09:37:10 +02:00

69 lines
2.3 KiB
Swift

//
// RelatedPanelPage.swift
// Yattee
//
// Details panel page listing videos related to the current one.
//
import SwiftUI
#if os(iOS) || os(macOS)
struct RelatedPanelPage: View {
let context: PanelPageContext
var settings: RelatedPageSettings = RelatedPageSettings()
var scrollConfig: PanelScrollConfig = PanelScrollConfig()
private var relatedVideos: [Video] { context.video.relatedVideos ?? [] }
var body: some View {
PanelPageScrollView(config: scrollConfig) {
if relatedVideos.isEmpty {
emptyState
} else {
LazyVStack(spacing: 12) {
ForEach(Array(relatedVideos.enumerated()), id: \.element.id) { index, relatedVideo in
VideoRowView(
video: relatedVideo,
style: .regular,
showThumbnail: settings.effectiveShowThumbnails
)
.tappableVideo(
relatedVideo,
queueSource: .manual,
sourceLabel: String(localized: "videoInfo.section.relatedVideos"),
videoList: relatedVideos,
videoIndex: index,
loadMoreVideos: nil
)
if index < relatedVideos.count - 1 {
Divider()
.padding(.leading, settings.effectiveShowThumbnails
? VideoRowStyle.regular.thumbnailWidth + 12
: 0)
}
}
}
.padding(.horizontal)
.padding(.top, 8)
}
}
}
private var emptyState: some View {
VStack(spacing: 8) {
Image(systemName: "rectangle.stack.badge.play")
.font(.title2)
.foregroundStyle(.secondary)
Text(String(localized: "videoInfo.section.relatedVideos"))
.font(.subheadline)
.foregroundStyle(.secondary)
}
.frame(maxWidth: .infinity)
.padding(.vertical, 32)
}
}
#endif