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.
This commit is contained in:
Arkadiusz Fal
2026-09-23 23:47:21 +02:00
parent e7458ba629
commit 4a85f7355a
4 changed files with 27 additions and 15 deletions

View File

@@ -19,7 +19,6 @@ struct ChaptersPanelPage: View {
private var playerState: PlayerState? { playerService?.state }
private var chapters: [VideoChapter] { playerState?.chapters ?? [] }
private var currentTime: TimeInterval { playerState?.currentTime ?? 0 }
private var storyboard: Storyboard? { playerState?.preferredStoryboard }
var body: some View {
@@ -50,9 +49,8 @@ struct ChaptersPanelPage: View {
}
private func isChapterActive(_ chapter: VideoChapter) -> Bool {
let nextChapter = chapters.first { $0.startTime > chapter.startTime }
let endTime = nextChapter?.startTime ?? .infinity
return currentTime >= chapter.startTime && currentTime < endTime
// Observes only chapter transitions, not per-tick currentTime updates.
playerState?.activeChapterID == chapter.id
}
private func preloadChapterSheets() async {

View File

@@ -230,7 +230,6 @@ struct InfoPanelPage: View {
// MARK: - Inline Sections (prototype)
private var chapters: [VideoChapter] { playerState?.chapters ?? [] }
private var currentTime: TimeInterval { playerState?.currentTime ?? 0 }
private var storyboard: Storyboard? { playerState?.preferredStoryboard }
private var relatedVideos: [Video] { video.relatedVideos ?? [] }
@@ -308,9 +307,8 @@ struct InfoPanelPage: View {
}
private func isChapterActive(_ chapter: VideoChapter) -> Bool {
let nextChapter = chapters.first { $0.startTime > chapter.startTime }
let endTime = nextChapter?.startTime ?? .infinity
return currentTime >= chapter.startTime && currentTime < endTime
// Observes only chapter transitions, not per-tick currentTime updates.
playerState?.activeChapterID == chapter.id
}
private func preloadChapterSheets() async {

View File

@@ -92,7 +92,6 @@ struct TVChaptersPanelList: View {
private var playerState: PlayerState? { playerService?.state }
private var chapters: [VideoChapter] { playerState?.chapters ?? [] }
private var currentTime: TimeInterval { playerState?.currentTime ?? 0 }
var body: some View {
ScrollViewReader { proxy in
@@ -124,9 +123,8 @@ struct TVChaptersPanelList: View {
}
private func isChapterActive(_ chapter: VideoChapter) -> Bool {
let nextChapter = chapters.first { $0.startTime > chapter.startTime }
let endTime = nextChapter?.startTime ?? .infinity
return currentTime >= chapter.startTime && currentTime < endTime
// Observes only chapter transitions, not per-tick currentTime updates.
playerState?.activeChapterID == chapter.id
}
}