Files
yattee/Yattee/Views/Player/Panels/ChaptersPanelPage.swift
Arkadiusz Fal 4a85f7355a Track the active chapter in PlayerState instead of per-tick time reads
Chapter lists highlighted the active row by reading currentTime in the
view body, re-rendering every row many times per second during
playback. PlayerState now stores a change-guarded activeChapterID
updated when time or chapters change, so views observe only chapter
transitions.
2026-09-23 23:47:21 +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)
}
}
)
}
}
.padding(.horizontal)
.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