New details page button

This commit is contained in:
Arkadiusz Fal 2022-12-18 22:34:22 +01:00
parent 467f50715c
commit 9bde57e4eb
4 changed files with 149 additions and 52 deletions

View File

@ -8,14 +8,10 @@ struct ChaptersView: View {
var body: some View { var body: some View {
if let chapters = player.currentVideo?.chapters, !chapters.isEmpty { if let chapters = player.currentVideo?.chapters, !chapters.isEmpty {
List { List {
Section(header: Text("Chapters")) { Section {
ForEach(chapters) { chapter in ForEach(chapters) { chapter in
ChapterView(chapter: chapter) ChapterView(chapter: chapter)
} }
Color.clear.frame(height: 50)
.listRowBackground(Color.clear)
.backport
.listRowSeparator(false)
} }
.listRowBackground(Color.clear) .listRowBackground(Color.clear)
} }

View File

@ -25,7 +25,7 @@ struct CommentsView: View {
.borderBottom(height: comment != last ? 0.5 : 0, color: Color("ControlsBorderColor")) .borderBottom(height: comment != last ? 0.5 : 0, color: Color("ControlsBorderColor"))
} }
} }
.padding(.top, 10) .padding(.top, 55)
if embedInScrollView { if embedInScrollView {
ScrollView(.vertical, showsIndicators: false) { ScrollView(.vertical, showsIndicators: false) {

View File

@ -53,7 +53,7 @@ struct InspectorView: View {
NoCommentsView(text: "Not playing", systemImage: "stop.circle.fill") NoCommentsView(text: "Not playing", systemImage: "stop.circle.fill")
} }
} }
.padding(.top, 10) .padding(.top, 60)
.padding(.bottom, 50) .padding(.bottom, 50)
} }
.padding(.horizontal) .padding(.horizontal)

View File

@ -5,7 +5,24 @@ import SwiftUI
struct VideoDetails: View { struct VideoDetails: View {
enum DetailsPage: String, CaseIterable, Defaults.Serializable { enum DetailsPage: String, CaseIterable, Defaults.Serializable {
case info, inspector, chapters, comments, related, queue case info, comments, chapters, inspector
var systemImageName: String {
switch self {
case .info:
return "info.circle"
case .inspector:
return "wand.and.stars"
case .comments:
return "text.bubble"
case .chapters:
return "bookmark"
}
}
var title: String {
rawValue.capitalized.localized()
}
} }
var video: Video? var video: Video?
@ -17,6 +34,7 @@ struct VideoDetails: View {
@State private var descriptionVisibility = Constants.descriptionVisibility @State private var descriptionVisibility = Constants.descriptionVisibility
@State private var subscribed = false @State private var subscribed = false
@State private var subscriptionToggleButtonDisabled = false @State private var subscriptionToggleButtonDisabled = false
@State private var page = DetailsPage.info
@Environment(\.navigationStyle) private var navigationStyle @Environment(\.navigationStyle) private var navigationStyle
#if os(iOS) #if os(iOS)
@ -48,10 +66,7 @@ struct VideoDetails: View {
VideoActions(video: player.videoForDisplay) VideoActions(video: player.videoForDisplay)
.animation(nil, value: player.currentItem) .animation(nil, value: player.currentItem)
detailsPage pageView
#if os(iOS)
.frame(maxWidth: maxWidth)
#endif
} }
.overlay(GeometryReader { proxy in .overlay(GeometryReader { proxy in
Color.clear Color.clear
@ -81,57 +96,143 @@ struct VideoDetails: View {
ContentItem(video: player.currentVideo) ContentItem(video: player.currentVideo)
} }
var detailsPage: some View { var pageMenu: some View {
ScrollView(.vertical, showsIndicators: false) { #if os(macOS)
if let video { pagePicker
VStack(alignment: .leading, spacing: 10) { .labelsHidden()
videoProperties .offset(x: 15, y: 15)
#if os(iOS) .frame(maxWidth: 200)
.opacity(descriptionVisibility ? 1 : 0) #else
#endif Menu {
pagePicker
} label: {
HStack {
Label(page.title, systemImage: page.systemImageName)
Image(systemName: "chevron.up.chevron.down")
.imageScale(.small)
}
.padding(10)
.fixedSize(horizontal: true, vertical: false)
.modifier(ControlBackgroundModifier())
.clipShape(RoundedRectangle(cornerRadius: 6))
.frame(width: 200, alignment: .leading)
.transaction { t in t.animation = nil }
}
.modifier(SettingsPickerModifier())
.offset(x: 15, y: 5)
#endif
}
if !player.videoBeingOpened.isNil && (video.description.isNil || video.description!.isEmpty) { var pagePicker: some View {
VStack { Picker("Page", selection: $page) {
ProgressView() ForEach(DetailsPage.allCases, id: \.rawValue) { page in
.progressViewStyle(.circular) Label(page.title, systemImage: page.systemImageName).tag(page)
}
}
}
var pageView: some View {
ZStack(alignment: .topLeading) {
switch page {
case .info:
ScrollView(.vertical, showsIndicators: false) {
if let video {
VStack(alignment: .leading, spacing: 10) {
HStack {
videoProperties
.frame(maxWidth: .infinity, alignment: .trailing)
#if os(iOS)
.opacity(descriptionVisibility ? 1 : 0)
#endif
}
.padding(.bottom, 12)
if !player.videoBeingOpened.isNil && (video.description.isNil || video.description!.isEmpty) {
VStack {
ProgressView()
.progressViewStyle(.circular)
}
.frame(maxWidth: .infinity)
.opacity(descriptionVisibility ? 1 : 0)
} else if video.description != nil, !video.description!.isEmpty {
VideoDescription(video: video, detailsSize: detailsSize)
#if os(iOS)
.opacity(descriptionVisibility ? 1 : 0)
.padding(.bottom, player.playingFullScreen ? 10 : SafeArea.insets.bottom)
#endif
} else if !video.isLocal {
Text("No description")
.font(.caption)
.foregroundColor(.secondary)
}
} }
.frame(maxWidth: .infinity) .padding(.top, 18)
.opacity(descriptionVisibility ? 1 : 0) .padding(.bottom, 60)
} else if video.description != nil, !video.description!.isEmpty {
VideoDescription(video: video, detailsSize: detailsSize)
#if os(iOS)
.opacity(descriptionVisibility ? 1 : 0)
.padding(.bottom, player.playingFullScreen ? 10 : SafeArea.insets.bottom)
#endif
} else if !video.isLocal {
Text("No description")
.font(.caption)
.foregroundColor(.secondary)
} }
} }
.padding(.top, 10) #if os(iOS)
.padding(.bottom, 60) .onAppear {
if fullScreen {
descriptionVisibility = true
return
}
Delay.by(0.4) { withAnimation(.easeIn(duration: 0.25)) { self.descriptionVisibility = true } }
}
#endif
.transition(.opacity)
.animation(nil, value: player.currentItem)
.padding(.horizontal)
#if os(iOS)
.frame(maxWidth: YatteeApp.isForPreviews ? .infinity : maxWidth)
#endif
case .inspector:
InspectorView(video: video)
case .chapters:
ChaptersView()
case .comments:
CommentsView(embedInScrollView: true)
.onAppear {
comments.loadIfNeeded()
}
} }
pageMenu
.font(.headline)
.foregroundColor(.accentColor)
.zIndex(1)
#if !os(tvOS)
Rectangle()
.fill(
LinearGradient(
gradient: .init(colors: [fadePlaceholderStartColor, .clear]),
startPoint: .top,
endPoint: .bottom
)
)
.zIndex(0)
.frame(maxHeight: 15)
#endif
} }
#if os(iOS) }
.onAppear {
if fullScreen { var fadePlaceholderStartColor: Color {
descriptionVisibility = true #if os(macOS)
return .secondaryBackground
} #elseif os(iOS)
Delay.by(0.4) { withAnimation(.easeIn(duration: 0.25)) { self.descriptionVisibility = true } } .background
}
#endif #endif
.transition(.opacity)
.animation(nil, value: player.currentItem)
.padding(.horizontal)
} }
@ViewBuilder var videoProperties: some View { @ViewBuilder var videoProperties: some View {
HStack(spacing: 2) { HStack(spacing: 4) {
Spacer()
publishedDateSection publishedDateSection
Spacer() Text("")
HStack(spacing: 4) { HStack(spacing: 4) {
Image(systemName: "eye") Image(systemName: "eye")
@ -173,7 +274,7 @@ struct VideoDetails: View {
} }
} }
} }
.font(.system(size: 12)) .font(.caption)
.foregroundColor(.secondary) .foregroundColor(.secondary)
} }