1
0
mirror of https://github.com/yattee/yattee.git synced 2024-12-13 22:00:31 +05:30

New chapters layout

This commit is contained in:
Arkadiusz Fal 2023-04-22 20:06:30 +02:00
parent d52ccf2ce6
commit 6596a440a5
7 changed files with 142 additions and 39 deletions

View File

@ -11,25 +11,53 @@ struct ChapterView: View {
Button {
player.backend.seek(to: chapter.start, seekType: .userInteracted)
} label: {
HStack(spacing: 12) {
if !chapter.image.isNil {
smallImage(chapter)
}
VStack(alignment: .leading, spacing: 4) {
Text(chapter.title)
.font(.headline)
Text(chapter.start.formattedAsPlaybackTime(allowZero: true) ?? "")
.font(.system(.subheadline).monospacedDigit())
.foregroundColor(.secondary)
}
Group {
#if os(tvOS)
horizontalChapter
#else
verticalChapter
#endif
}
.frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle())
}
.buttonStyle(.plain)
}
var horizontalChapter: some View {
HStack(spacing: 12) {
if !chapter.image.isNil {
smallImage(chapter)
}
VStack(alignment: .leading, spacing: 4) {
Text(chapter.title)
.font(.headline)
Text(chapter.start.formattedAsPlaybackTime(allowZero: true) ?? "")
.font(.system(.subheadline).monospacedDigit())
.foregroundColor(.secondary)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
}
var verticalChapter: some View {
VStack(spacing: 12) {
if !chapter.image.isNil {
smallImage(chapter)
}
VStack(alignment: .leading, spacing: 4) {
Text(chapter.title)
.lineLimit(2)
.multilineTextAlignment(.leading)
.font(.headline)
Text(chapter.start.formattedAsPlaybackTime(allowZero: true) ?? "")
.font(.system(.subheadline).monospacedDigit())
.foregroundColor(.secondary)
}
.frame(maxWidth: Self.thumbnailWidth, alignment: .leading)
}
}
@ViewBuilder func smallImage(_ chapter: Chapter) -> some View {
WebImage(url: chapter.image, options: [.lowPriority])
.resizable()
@ -37,21 +65,20 @@ struct ChapterView: View {
ProgressView()
}
.indicator(.activity)
.frame(width: Self.thumbnailWidth, height: Self.thumbnailHeight)
#if os(tvOS)
.frame(width: thumbnailWidth, height: 140)
.mask(RoundedRectangle(cornerRadius: 12))
#else
.frame(width: thumbnailWidth, height: 60)
.mask(RoundedRectangle(cornerRadius: 6))
#endif
}
private var thumbnailWidth: Double {
#if os(tvOS)
250
#else
100
#endif
static var thumbnailWidth: Double {
250
}
static var thumbnailHeight: Double {
thumbnailWidth / 1.7777
}
}

View File

@ -5,24 +5,32 @@ import SwiftUI
struct ChaptersView: View {
@ObservedObject private var player = PlayerModel.shared
var chapters: [Chapter] {
player.videoForDisplay?.chapters ?? []
}
var body: some View {
if let chapters = player.currentVideo?.chapters, !chapters.isEmpty {
List {
Section {
ForEach(chapters) { chapter in
ChapterView(chapter: chapter)
if !chapters.isEmpty {
#if os(tvOS)
List {
Section {
ForEach(chapters) { chapter in
ChapterView(chapter: chapter)
}
}
.listRowBackground(Color.clear)
}
.listRowBackground(Color.clear)
}
#if os(macOS)
.listStyle(.inset)
#elseif os(iOS)
.listStyle(.grouped)
.backport
.scrollContentBackground(false)
.listStyle(.plain)
#else
.listStyle(.plain)
ScrollView(.horizontal) {
LazyHStack(spacing: 20) {
ForEach(chapters) { chapter in
ChapterView(chapter: chapter)
}
}
.padding(.horizontal, 15)
}
.frame(minHeight: ChapterView.thumbnailHeight + 100)
#endif
} else {
NoCommentsView(text: "No chapters information available".localized(), systemImage: "xmark.circle.fill")

View File

@ -50,6 +50,7 @@ struct VideoDescription: View {
keywords
}
.contentShape(Rectangle())
}
var shouldExpand: Bool {

View File

@ -285,21 +285,37 @@ struct VideoDetails: View {
} else if let description = video.description, !description.isEmpty {
Section(header: descriptionHeader) {
VideoDescription(video: video, detailsSize: detailsSize, expand: $descriptionExpanded)
.padding(.horizontal)
}
} else if !video.isLocal {
Text("No description")
.font(.caption)
.foregroundColor(.secondary)
.padding(.horizontal)
}
if video.isLocal || showInspector == .always {
if player.videoBeingOpened.isNil,
!video.isLocal,
!video.chapters.isEmpty
{
Section(header: chaptersHeader) {
ChaptersView()
}
}
if player.videoBeingOpened.isNil,
video.isLocal || showInspector == .always
{
InspectorView(video: player.videoForDisplay)
.padding(.horizontal)
}
if !sidebarQueue,
if player.videoBeingOpened.isNil,
!sidebarQueue,
!(player.videoForDisplay?.related.isEmpty ?? true)
{
RelatedView()
.padding(.horizontal)
.padding(.top, 20)
}
}
@ -313,7 +329,6 @@ struct VideoDetails: View {
}
.transition(.opacity)
.animation(nil, value: player.currentItem)
.padding(.horizontal)
#if os(iOS)
.frame(maxWidth: YatteeApp.isForPreviews ? .infinity : maxWidth)
#endif
@ -360,9 +375,17 @@ struct VideoDetails: View {
.imageScale(.small)
}
}
.padding(.horizontal)
.font(.caption)
.foregroundColor(.secondary)
}
var chaptersHeader: some View {
Text("Chapters".localized())
.padding(.horizontal)
.font(.caption)
.foregroundColor(.secondary)
}
}
struct VideoDetails_Previews: PreviewProvider {

View File

@ -412,7 +412,7 @@ struct VideoPlayerView: View {
List {
PlayerQueueView(sidebarQueue: true)
}
.frame(maxWidth: 350)
.frame(maxWidth: 450)
.background(colorScheme == .dark ? Color.black : Color.white)
}
#endif
@ -431,6 +431,7 @@ struct VideoPlayerView: View {
}
)
#endif
.ignoresSafeArea(edges: .horizontal)
}
var fullScreenPlayer: Bool {

View File

@ -561,6 +561,48 @@ struct SearchView: View {
searchSortOrder.rawValue
))
}
var shouldDisplayHeader: Bool {
#if os(tvOS)
!state.query.isEmpty
#else
false
#endif
}
var header: some View {
HStack {
clearButton
#if os(tvOS)
if accounts.app.supportsSearchFilters {
filtersHorizontalStack
}
#endif
FavoriteButton(item: favoriteItem)
.id(favoriteItem?.id)
.labelStyle(.iconOnly)
.font(.system(size: 25))
Spacer()
ListingStyleButtons(listingStyle: $searchListingStyle)
HideShortsButtons(hide: $hideShorts)
}
.labelStyle(.iconOnly)
.padding(.leading, 30)
.padding(.bottom, 15)
.padding(.trailing, 30)
}
var clearButton: some View {
Button {
state.queryText = ""
} label: {
Label("Clear", systemImage: "xmark")
.labelStyle(.iconOnly)
}
.font(.caption)
}
}
struct SearchView_Previews: PreviewProvider {

View File

@ -131,6 +131,7 @@ struct NowPlayingView: View {
Section(header: Text("Chapters")) {
ForEach(video.chapters) { chapter in
ChapterView(chapter: chapter)
.padding(.horizontal, 40)
}
}
}