mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 21:43:41 +00:00
Regular TV layout
This commit is contained in:
parent
44600831a6
commit
945dbfe00b
@ -45,7 +45,7 @@ struct FixtureEnvironmentObjectsModifier: ViewModifier {
|
|||||||
player.currentItem = PlayerQueueItem(
|
player.currentItem = PlayerQueueItem(
|
||||||
Video(
|
Video(
|
||||||
videoID: "",
|
videoID: "",
|
||||||
title: "",
|
title: "Video Name",
|
||||||
author: "",
|
author: "",
|
||||||
length: 0,
|
length: 0,
|
||||||
published: "2 days ago",
|
published: "2 days ago",
|
||||||
|
@ -102,8 +102,8 @@ extension Defaults.Keys {
|
|||||||
static let playerControlsLayoutDefault = UIDevice.current.userInterfaceIdiom == .pad ? PlayerControlsLayout.medium : .small
|
static let playerControlsLayoutDefault = UIDevice.current.userInterfaceIdiom == .pad ? PlayerControlsLayout.medium : .small
|
||||||
static let fullScreenPlayerControlsLayoutDefault = UIDevice.current.userInterfaceIdiom == .pad ? PlayerControlsLayout.medium : .small
|
static let fullScreenPlayerControlsLayoutDefault = UIDevice.current.userInterfaceIdiom == .pad ? PlayerControlsLayout.medium : .small
|
||||||
#elseif os(tvOS)
|
#elseif os(tvOS)
|
||||||
static let playerControlsLayoutDefault = PlayerControlsLayout.veryLarge
|
static let playerControlsLayoutDefault = PlayerControlsLayout.tvRegular
|
||||||
static let fullScreenPlayerControlsLayoutDefault = PlayerControlsLayout.veryLarge
|
static let fullScreenPlayerControlsLayoutDefault = PlayerControlsLayout.tvRegular
|
||||||
#else
|
#else
|
||||||
static let playerControlsLayoutDefault = PlayerControlsLayout.medium
|
static let playerControlsLayoutDefault = PlayerControlsLayout.medium
|
||||||
static let fullScreenPlayerControlsLayoutDefault = PlayerControlsLayout.medium
|
static let fullScreenPlayerControlsLayoutDefault = PlayerControlsLayout.medium
|
||||||
@ -129,7 +129,12 @@ extension Defaults.Keys {
|
|||||||
#if !os(macOS)
|
#if !os(macOS)
|
||||||
static let pauseOnEnteringBackground = Key<Bool>("pauseOnEnteringBackground", default: true)
|
static let pauseOnEnteringBackground = Key<Bool>("pauseOnEnteringBackground", default: true)
|
||||||
#endif
|
#endif
|
||||||
static let closeLastItemOnPlaybackEnd = Key<Bool>("closeLastItemOnPlaybackEnd", default: false)
|
#if os(tvOS)
|
||||||
|
static let closeLastItemOnPlaybackEndDefault = true
|
||||||
|
#else
|
||||||
|
static let closeLastItemOnPlaybackEndDefault = false
|
||||||
|
#endif
|
||||||
|
static let closeLastItemOnPlaybackEnd = Key<Bool>("closeLastItemOnPlaybackEnd", default: closeLastItemOnPlaybackEndDefault)
|
||||||
|
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
static let closePlayerOnItemCloseDefault = true
|
static let closePlayerOnItemCloseDefault = true
|
||||||
|
@ -19,9 +19,9 @@ struct Seek: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Button(action: model.restoreTime) {
|
Button(action: model.restoreTime) {
|
||||||
VStack(spacing: 2) {
|
VStack(spacing: playerControlsLayout.osdSpacing) {
|
||||||
ProgressBar(value: progress)
|
ProgressBar(value: progress)
|
||||||
.frame(maxHeight: 5)
|
.frame(maxHeight: playerControlsLayout.osdProgressBarHeight)
|
||||||
|
|
||||||
timeline
|
timeline
|
||||||
|
|
||||||
@ -37,6 +37,7 @@ struct Seek: View {
|
|||||||
Text(chapter.title)
|
Text(chapter.title)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
.font(.system(size: playerControlsLayout.chapterFontSize))
|
.font(.system(size: playerControlsLayout.chapterFontSize))
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
}
|
}
|
||||||
if let segment = projectedSegment {
|
if let segment = projectedSegment {
|
||||||
Text(SponsorBlockAPI.categoryDescription(segment.category) ?? "Sponsor")
|
Text(SponsorBlockAPI.categoryDescription(segment.category) ?? "Sponsor")
|
||||||
@ -44,14 +45,15 @@ struct Seek: View {
|
|||||||
.foregroundColor(Color("AppRedColor"))
|
.foregroundColor(Color("AppRedColor"))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !model.restoreSeekTime.isNil {
|
#if !os(tvOS)
|
||||||
Divider()
|
if !model.restoreSeekTime.isNil {
|
||||||
Label(model.restoreSeekPlaybackTime, systemImage: "arrow.counterclockwise")
|
Divider()
|
||||||
.foregroundColor(.secondary)
|
Label(model.restoreSeekPlaybackTime, systemImage: "arrow.counterclockwise")
|
||||||
.font(.system(size: playerControlsLayout.chapterFontSize).monospacedDigit())
|
.foregroundColor(.secondary)
|
||||||
.frame(height: playerControlsLayout.chapterFontSize + 5)
|
.font(.system(size: playerControlsLayout.chapterFontSize).monospacedDigit())
|
||||||
}
|
.frame(height: playerControlsLayout.chapterFontSize + 5)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Group {
|
Group {
|
||||||
switch model.lastSeekType {
|
switch model.lastSeekType {
|
||||||
case let .segmentSkip(category):
|
case let .segmentSkip(category):
|
||||||
@ -67,7 +69,7 @@ struct Seek: View {
|
|||||||
}
|
}
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
.frame(minWidth: 250, minHeight: 100)
|
.frame(minWidth: 250, minHeight: 100)
|
||||||
.padding(10)
|
.padding(30)
|
||||||
#endif
|
#endif
|
||||||
.frame(maxWidth: playerControlsLayout.seekOSDWidth)
|
.frame(maxWidth: playerControlsLayout.seekOSDWidth)
|
||||||
.padding(2)
|
.padding(2)
|
||||||
|
@ -49,7 +49,7 @@ struct PlayerControls: View {
|
|||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
.frame(maxWidth: .infinity, alignment: .topLeading)
|
.frame(maxWidth: .infinity, alignment: .topLeading)
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
.offset(x: 10, y: 5)
|
.offset(x: 10, y: 10)
|
||||||
.focused($focusedField, equals: .seekOSD)
|
.focused($focusedField, equals: .seekOSD)
|
||||||
.onChange(of: player.playerTime.lastSeekTime) { _ in
|
.onChange(of: player.playerTime.lastSeekTime) { _ in
|
||||||
if !model.presentingControls {
|
if !model.presentingControls {
|
||||||
@ -108,8 +108,26 @@ struct PlayerControls: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
if playerControlsLayout.displaysTitleLine {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text(player.currentVideo?.title ?? "Not Playing")
|
||||||
|
.shadow(radius: 10)
|
||||||
|
.font(.system(size: playerControlsLayout.titleLineFontSize).bold())
|
||||||
|
.lineLimit(1)
|
||||||
|
|
||||||
|
Text(player.currentVideo?.channel.name ?? "")
|
||||||
|
.fontWeight(.semibold)
|
||||||
|
.shadow(radius: 10)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.font(.system(size: playerControlsLayout.authorLineFontSize))
|
||||||
|
.lineLimit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.offset(y: -40)
|
||||||
|
}
|
||||||
|
|
||||||
timeline
|
timeline
|
||||||
.frame(maxWidth: 1000)
|
|
||||||
.padding(.bottom, 2)
|
.padding(.bottom, 2)
|
||||||
}
|
}
|
||||||
.zIndex(1)
|
.zIndex(1)
|
||||||
@ -135,9 +153,6 @@ struct PlayerControls: View {
|
|||||||
musicModeButton
|
musicModeButton
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if os(tvOS)
|
|
||||||
.frame(width: 1200)
|
|
||||||
#endif
|
|
||||||
.zIndex(0)
|
.zIndex(0)
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
.offset(y: -playerControlsLayout.timelineHeight - 30)
|
.offset(y: -playerControlsLayout.timelineHeight - 30)
|
||||||
|
@ -2,6 +2,7 @@ import Defaults
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
||||||
|
case tvRegular
|
||||||
case veryLarge
|
case veryLarge
|
||||||
case large
|
case large
|
||||||
case medium
|
case medium
|
||||||
@ -10,6 +11,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var description: String {
|
var description: String {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return "TV"
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return "Very Large"
|
return "Very Large"
|
||||||
default:
|
default:
|
||||||
@ -19,6 +22,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var buttonsSpacing: Double {
|
var buttonsSpacing: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 80
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 40
|
return 40
|
||||||
case .large:
|
case .large:
|
||||||
@ -34,6 +39,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var buttonFontSize: Double {
|
var buttonFontSize: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 48
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 35
|
return 35
|
||||||
case .large:
|
case .large:
|
||||||
@ -49,6 +56,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var bigButtonFontSize: Double {
|
var bigButtonFontSize: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 65
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 55
|
return 55
|
||||||
case .large:
|
case .large:
|
||||||
@ -64,6 +73,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var buttonSize: Double {
|
var buttonSize: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 90
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 60
|
return 60
|
||||||
case .large:
|
case .large:
|
||||||
@ -79,6 +90,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var bigButtonSize: Double {
|
var bigButtonSize: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 100
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 85
|
return 85
|
||||||
case .large:
|
case .large:
|
||||||
@ -94,6 +107,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var segmentFontSize: Double {
|
var segmentFontSize: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 20
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 16
|
return 16
|
||||||
case .large:
|
case .large:
|
||||||
@ -109,6 +124,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var chapterFontSize: Double {
|
var chapterFontSize: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 24
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 20
|
return 20
|
||||||
case .large:
|
case .large:
|
||||||
@ -124,6 +141,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var projectedTimeFontSize: Double {
|
var projectedTimeFontSize: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 30
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 25
|
return 25
|
||||||
case .large:
|
case .large:
|
||||||
@ -139,6 +158,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var thumbSize: Double {
|
var thumbSize: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 45
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 35
|
return 35
|
||||||
case .large:
|
case .large:
|
||||||
@ -154,6 +175,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var timeFontSize: Double {
|
var timeFontSize: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 45
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 35
|
return 35
|
||||||
case .large:
|
case .large:
|
||||||
@ -169,6 +192,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var bufferingStateFontSize: Double {
|
var bufferingStateFontSize: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 45
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 30
|
return 30
|
||||||
case .large:
|
case .large:
|
||||||
@ -184,6 +209,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var timeLeadingEdgePadding: Double {
|
var timeLeadingEdgePadding: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 20
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 5
|
return 5
|
||||||
case .large:
|
case .large:
|
||||||
@ -199,6 +226,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var timeTrailingEdgePadding: Double {
|
var timeTrailingEdgePadding: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 20
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 16
|
return 16
|
||||||
case .large:
|
case .large:
|
||||||
@ -214,6 +243,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var timelineHeight: Double {
|
var timelineHeight: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 80
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 40
|
return 40
|
||||||
case .large:
|
case .large:
|
||||||
@ -229,6 +260,8 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
|
|
||||||
var seekOSDWidth: Double {
|
var seekOSDWidth: Double {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 240
|
||||||
case .veryLarge:
|
case .veryLarge:
|
||||||
return 240
|
return 240
|
||||||
case .large:
|
case .large:
|
||||||
@ -245,4 +278,50 @@ enum PlayerControlsLayout: String, CaseIterable, Defaults.Serializable {
|
|||||||
var osdVerticalOffset: Double {
|
var osdVerticalOffset: Double {
|
||||||
buttonSize
|
buttonSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var osdProgressBarHeight: Double {
|
||||||
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 20
|
||||||
|
case .veryLarge:
|
||||||
|
return 10
|
||||||
|
case .large:
|
||||||
|
return 8
|
||||||
|
case .medium:
|
||||||
|
return 5
|
||||||
|
case .small:
|
||||||
|
return 5
|
||||||
|
case .smaller:
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var osdSpacing: Double {
|
||||||
|
switch self {
|
||||||
|
case .tvRegular:
|
||||||
|
return 8
|
||||||
|
case .veryLarge:
|
||||||
|
return 8
|
||||||
|
case .large:
|
||||||
|
return 6
|
||||||
|
case .medium:
|
||||||
|
return 4
|
||||||
|
case .small:
|
||||||
|
return 2
|
||||||
|
case .smaller:
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var displaysTitleLine: Bool {
|
||||||
|
self == .tvRegular
|
||||||
|
}
|
||||||
|
|
||||||
|
var titleLineFontSize: Double {
|
||||||
|
60
|
||||||
|
}
|
||||||
|
|
||||||
|
var authorLineFontSize: Double {
|
||||||
|
30
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,9 @@ struct VideoPlayerView: View {
|
|||||||
@EnvironmentObject<PlayerModel> internal var player
|
@EnvironmentObject<PlayerModel> internal var player
|
||||||
@EnvironmentObject<PlayerControlsModel> internal var playerControls
|
@EnvironmentObject<PlayerControlsModel> internal var playerControls
|
||||||
@EnvironmentObject<RecentsModel> internal var recents
|
@EnvironmentObject<RecentsModel> internal var recents
|
||||||
@EnvironmentObject<SearchModel> internal var search
|
#if os(macOS)
|
||||||
|
@EnvironmentObject<SearchModel> internal var search
|
||||||
|
#endif
|
||||||
@EnvironmentObject<ThumbnailsModel> internal var thumbnails
|
@EnvironmentObject<ThumbnailsModel> internal var thumbnails
|
||||||
|
|
||||||
@Default(.horizontalPlayerGestureEnabled) var horizontalPlayerGestureEnabled
|
@Default(.horizontalPlayerGestureEnabled) var horizontalPlayerGestureEnabled
|
||||||
|
Loading…
Reference in New Issue
Block a user