Files
yattee/Yattee/Views/Player/ChaptersView.swift
Arkadiusz Fal 612dce6b9f Refactor views
2026-02-09 01:13:02 +01:00

101 lines
2.9 KiB
Swift

//
// ChaptersView.swift
// Yattee
//
// View for displaying and navigating video chapters.
//
import SwiftUI
struct ChaptersView: View {
@Environment(\.dismiss) private var dismiss
let chapters: [VideoChapter]
let currentTime: TimeInterval
let storyboard: Storyboard?
let onChapterTap: (VideoChapter) async -> Void
@State private var sheetsLoaded = false
var body: some View {
NavigationStack {
Group {
if sheetsLoaded {
chaptersList
} else {
ProgressView()
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
.navigationTitle(String(localized: "player.chapters"))
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button(role: .cancel) {
dismiss()
} label: {
Label(String(localized: "common.close"), systemImage: "xmark")
.labelStyle(.iconOnly)
}
}
}
.task {
await preloadChapterSheets()
sheetsLoaded = true
}
}
}
private var chaptersList: some View {
List {
ForEach(chapters) { chapter in
ChapterRow(
chapter: chapter,
isActive: isChapterActive(chapter),
storyboard: storyboard,
onTap: {
Task {
await onChapterTap(chapter)
dismiss()
}
}
)
}
}
.listStyle(.plain)
}
private func preloadChapterSheets() async {
guard let storyboard else { return }
let service = StoryboardService.shared
// Preload sheets for all chapter start times
for chapter in chapters {
await service.loadSheet(for: chapter.startTime, from: storyboard)
}
}
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
}
}
// MARK: - Preview
#Preview {
ChaptersView(
chapters: [
VideoChapter(title: "Introduction", startTime: 0),
VideoChapter(title: "Main Content", startTime: 60),
VideoChapter(title: "Deep Dive", startTime: 180),
VideoChapter(title: "Conclusion", startTime: 300),
],
currentTime: 90,
storyboard: nil,
onChapterTap: { _ in }
)
}