Files
yattee/Yattee/Views/Player/Panels/ChaptersPanelPage.swift
Arkadiusz Fal bfbb729a8c Align side column page content and tabs with the grabber inset
The corner layout side column puts a 12pt resize grabber strip before the
panel, and every page then added the standard 16pt horizontal padding, so
content sat ~28pt from the left edge but 16pt from the right.

Add a PanelHorizontalInsets environment value with a panelHorizontalPadding()
modifier that the info, comments, related and chapters pages use instead of
.padding(.horizontal). The side column trims the leading inset by the grabber
width so content is 16pt from the column's outer edge on both sides; other
hosts keep the defaults. Queue and tracks are List-backed and get the same
leading delta as a scroll content margin. The page bar follows the same insets
so the first pill lines up with the content.
2026-09-24 22:01:01 +02:00

66 lines
2.1 KiB
Swift

//
// ChaptersPanelPage.swift
// Yattee
//
// Details panel page listing video chapters; tapping seeks.
//
import SwiftUI
#if os(iOS) || os(macOS)
struct ChaptersPanelPage: View {
let context: PanelPageContext
var settings: ChaptersPageSettings = ChaptersPageSettings()
var scrollConfig: PanelScrollConfig = PanelScrollConfig()
private var appEnvironment: AppEnvironment? { context.appEnvironment }
private var playerService: PlayerService? { appEnvironment?.playerService }
private var playerState: PlayerState? { playerService?.state }
private var chapters: [VideoChapter] { playerState?.chapters ?? [] }
private var storyboard: Storyboard? { playerState?.preferredStoryboard }
var body: some View {
PanelPageScrollView(config: scrollConfig) {
LazyVStack(spacing: 0) {
ForEach(chapters) { chapter in
ChapterRow(
chapter: chapter,
isActive: isChapterActive(chapter),
storyboard: storyboard,
showThumbnail: settings.effectiveShowThumbnails,
onTap: {
Task {
await playerService?.seek(to: chapter.startTime)
}
}
)
}
}
.panelHorizontalPadding()
.padding(.top, 8)
}
.task(id: context.video.id) {
if settings.effectiveShowThumbnails {
await preloadChapterSheets()
}
}
}
private func isChapterActive(_ chapter: VideoChapter) -> Bool {
// Observes only chapter transitions, not per-tick currentTime updates.
playerState?.activeChapterID == chapter.id
}
private func preloadChapterSheets() async {
guard let storyboard else { return }
let service = StoryboardService.shared
for chapter in chapters {
await service.loadSheet(for: chapter.startTime, from: storyboard)
}
}
}
#endif