From 4ec6f35c5d74c50e4691ac4ef89cb2a5e57d0f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toni=20F=C3=B6rster?= Date: Tue, 28 Nov 2023 16:45:36 +0100 Subject: [PATCH] highlight current chapter --- Model/Player/PlayerModel.swift | 3 ++ Shared/Player/Video Details/ChapterView.swift | 29 ++++++++++++++++--- .../Player/Video Details/ChaptersView.swift | 18 ++++++++---- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/Model/Player/PlayerModel.swift b/Model/Player/PlayerModel.swift index d9835211..1da1d8c8 100644 --- a/Model/Player/PlayerModel.swift +++ b/Model/Player/PlayerModel.swift @@ -131,6 +131,9 @@ final class PlayerModel: ObservableObject { @Default(.rotateToLandscapeOnEnterFullScreen) private var rotateToLandscapeOnEnterFullScreen #endif + @Published var playedChapters: [Int] = [] + @Published var currentChapterIndex: Int? + var accounts: AccountsModel { .shared } var comments: CommentsModel { .shared } var controls: PlayerControlsModel { .shared } diff --git a/Shared/Player/Video Details/ChapterView.swift b/Shared/Player/Video Details/ChapterView.swift index ab5bcbd7..ca10ace8 100644 --- a/Shared/Player/Video Details/ChapterView.swift +++ b/Shared/Player/Video Details/ChapterView.swift @@ -1,16 +1,27 @@ +import CoreMedia import Foundation import SDWebImageSwiftUI import SwiftUI struct ChapterView: View { var chapter: Chapter + var nextChapterStart: Double? - var player = PlayerModel.shared + var chapterIndex: Int + @ObservedObject private var player = PlayerModel.shared + + var isCurrentChapter: Bool { + player.currentChapterIndex == chapterIndex + } + + var hasBeenPlayed: Bool { + player.playedChapters.contains(chapterIndex) + } var body: some View { - Button { + Button(action: { player.backend.seek(to: chapter.start, seekType: .userInteracted) - } label: { + }) { Group { #if os(tvOS) horizontalChapter @@ -21,6 +32,15 @@ struct ChapterView: View { .contentShape(Rectangle()) } .buttonStyle(.plain) + .onReceive(PlayerTimeModel.shared.$currentTime) { cmTime in + let time = CMTimeGetSeconds(cmTime) + if time >= self.chapter.start, self.nextChapterStart == nil || time < self.nextChapterStart! { + player.currentChapterIndex = self.chapterIndex + if !player.playedChapters.contains(self.chapterIndex) { + player.playedChapters.append(self.chapterIndex) + } + } + } } #if os(tvOS) @@ -52,6 +72,7 @@ struct ChapterView: View { .lineLimit(3) .multilineTextAlignment(.leading) .font(.headline) + .foregroundColor(isCurrentChapter ? .detailBadgeOutstandingStyleBackground : .primary) Text(chapter.start.formattedAsPlaybackTime(allowZero: true) ?? "") .font(.system(.subheadline).monospacedDigit()) .foregroundColor(.secondary) @@ -87,7 +108,7 @@ struct ChapterView: View { struct ChapterView_Preview: PreviewProvider { static var previews: some View { - ChapterView(chapter: .init(title: "Chapter", start: 30)) + ChapterView(chapter: .init(title: "Chapter", start: 30), chapterIndex: 0) .injectFixtureEnvironmentObjects() } } diff --git a/Shared/Player/Video Details/ChaptersView.swift b/Shared/Player/Video Details/ChaptersView.swift index 5f2bb17f..55547886 100644 --- a/Shared/Player/Video Details/ChaptersView.swift +++ b/Shared/Player/Video Details/ChaptersView.swift @@ -30,8 +30,10 @@ struct ChaptersView: View { #else ScrollView(.horizontal) { LazyHStack(spacing: 20) { - ForEach(chapters) { chapter in - ChapterView(chapter: chapter) + ForEach(Array(chapters.indices), id: \.self) { index in + let chapter = chapters[index] + let nextChapterStart: Double? = index < chapters.count - 1 ? chapters[index + 1].start : nil + ChapterView(chapter: chapter, nextChapterStart: nextChapterStart, chapterIndex: index) } } .padding(.horizontal, 15) @@ -39,8 +41,10 @@ struct ChaptersView: View { #endif } else if expand { Section { - ForEach(chapters) { chapter in - ChapterView(chapter: chapter) + ForEach(Array(chapters.indices), id: \.self) { index in + let chapter = chapters[index] + let nextChapterStart: Double? = index < chapters.count - 1 ? chapters[index + 1].start : nil + ChapterView(chapter: chapter, nextChapterStart: nextChapterStart, chapterIndex: index) } } .padding(.horizontal) @@ -60,8 +64,10 @@ struct ChaptersView: View { var contents: some View { Section { - ForEach(chapters.prefix(3).indices, id: \.self) { index in - ChapterView(chapter: chapters[index]) + ForEach(Array(chapters.prefix(3).indices), id: \.self) { index in + let chapter = chapters[index] + let nextChapterStart: Double? = index < chapters.count - 1 ? chapters[index + 1].start : nil + ChapterView(chapter: chapter, nextChapterStart: nextChapterStart, chapterIndex: index) .allowsHitTesting(expand) .opacity(index == 0 ? 1.0 : 0.3) }