mirror of
https://github.com/yattee/yattee.git
synced 2024-11-09 15:58:20 +00:00
Details panels in controls
This commit is contained in:
parent
db46289813
commit
f0b8e7f655
12
Backports/ScrollContentBackground+Backport.swift
Normal file
12
Backports/ScrollContentBackground+Backport.swift
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
extension Backport where Content: View {
|
||||||
|
@ViewBuilder func scrollContentBackground(_ visibility: Bool) -> some View {
|
||||||
|
if #available(iOS 16.0, macOS 13.0, tvOS 16.0, *) {
|
||||||
|
content.scrollContentBackground(visibility ? .visible : .hidden)
|
||||||
|
} else {
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -96,23 +96,19 @@ final class NavigationModel: ObservableObject {
|
|||||||
player.hide()
|
player.hide()
|
||||||
navigation.presentingChannel = false
|
navigation.presentingChannel = false
|
||||||
|
|
||||||
let recent = RecentItem(from: channel)
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
Windows.main.open()
|
Windows.main.open()
|
||||||
#else
|
|
||||||
player.hide()
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
let recent = RecentItem(from: channel)
|
||||||
recents.add(recent)
|
recents.add(RecentItem(from: channel))
|
||||||
|
|
||||||
if navigationStyle == .sidebar {
|
if navigationStyle == .sidebar {
|
||||||
navigation.sidebarSectionChanged.toggle()
|
navigation.sidebarSectionChanged.toggle()
|
||||||
navigation.tabSelection = .recentlyOpened(recent.tag)
|
navigation.tabSelection = .recentlyOpened(recent.tag)
|
||||||
} else {
|
} else {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
navigation.presentingChannel = true
|
navigation.presentingChannel = true
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ final class PlayerControlsModel: ObservableObject {
|
|||||||
@Published var isPlaying = true
|
@Published var isPlaying = true
|
||||||
@Published var presentingControls = false { didSet { handlePresentationChange() } }
|
@Published var presentingControls = false { didSet { handlePresentationChange() } }
|
||||||
@Published var presentingControlsOverlay = false { didSet { handleOverlayPresentationChange() } }
|
@Published var presentingControlsOverlay = false { didSet { handleOverlayPresentationChange() } }
|
||||||
|
@Published var presentingDetailsOverlay = false
|
||||||
@Published var timer: Timer?
|
@Published var timer: Timer?
|
||||||
|
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
@ -21,6 +22,7 @@ final class PlayerControlsModel: ObservableObject {
|
|||||||
isPlaying: Bool = true,
|
isPlaying: Bool = true,
|
||||||
presentingControls: Bool = false,
|
presentingControls: Bool = false,
|
||||||
presentingControlsOverlay: Bool = false,
|
presentingControlsOverlay: Bool = false,
|
||||||
|
presentingDetailsOverlay: Bool = false,
|
||||||
timer: Timer? = nil,
|
timer: Timer? = nil,
|
||||||
player: PlayerModel? = nil
|
player: PlayerModel? = nil
|
||||||
) {
|
) {
|
||||||
@ -28,20 +30,22 @@ final class PlayerControlsModel: ObservableObject {
|
|||||||
self.isPlaying = isPlaying
|
self.isPlaying = isPlaying
|
||||||
self.presentingControls = presentingControls
|
self.presentingControls = presentingControls
|
||||||
self.presentingControlsOverlay = presentingControlsOverlay
|
self.presentingControlsOverlay = presentingControlsOverlay
|
||||||
|
self.presentingDetailsOverlay = presentingDetailsOverlay
|
||||||
self.timer = timer
|
self.timer = timer
|
||||||
self.player = player
|
self.player = player
|
||||||
}
|
}
|
||||||
|
|
||||||
func handlePresentationChange() {
|
func handlePresentationChange() {
|
||||||
if presentingControls {
|
DispatchQueue.main.async { [weak self] in
|
||||||
DispatchQueue.main.async { [weak self] in
|
guard let self = self else { return }
|
||||||
self?.player?.backend.startControlsUpdates()
|
if self.presentingControls {
|
||||||
self?.resetTimer()
|
self.player?.backend.startControlsUpdates()
|
||||||
|
self.resetTimer()
|
||||||
|
} else {
|
||||||
|
self.player?.backend.stopControlsUpdates()
|
||||||
|
self.timer?.invalidate()
|
||||||
|
self.timer = nil
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
player?.backend.stopControlsUpdates()
|
|
||||||
timer?.invalidate()
|
|
||||||
timer = nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +58,15 @@ final class PlayerControlsModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var presentingOverlays: Bool {
|
||||||
|
presentingDetailsOverlay || presentingControlsOverlay
|
||||||
|
}
|
||||||
|
|
||||||
|
func hideOverlays() {
|
||||||
|
presentingDetailsOverlay = false
|
||||||
|
presentingControlsOverlay = false
|
||||||
|
}
|
||||||
|
|
||||||
func show() {
|
func show() {
|
||||||
guard !(player?.currentItem.isNil ?? true) else {
|
guard !(player?.currentItem.isNil ?? true) else {
|
||||||
return
|
return
|
||||||
|
@ -98,7 +98,13 @@ final class PlayerModel: ObservableObject {
|
|||||||
var context: NSManagedObjectContext = PersistenceController.shared.container.viewContext
|
var context: NSManagedObjectContext = PersistenceController.shared.container.viewContext
|
||||||
var backgroundContext = PersistenceController.shared.container.newBackgroundContext()
|
var backgroundContext = PersistenceController.shared.container.newBackgroundContext()
|
||||||
|
|
||||||
@Published var playingFullScreen = false
|
#if os(tvOS)
|
||||||
|
static let fullScreenIsDefault = true
|
||||||
|
#else
|
||||||
|
static let fullScreenIsDefault = false
|
||||||
|
#endif
|
||||||
|
@Published var playingFullScreen = PlayerModel.fullScreenIsDefault
|
||||||
|
|
||||||
@Published var playingInPictureInPicture = false
|
@Published var playingInPictureInPicture = false
|
||||||
var pipController: AVPictureInPictureController?
|
var pipController: AVPictureInPictureController?
|
||||||
var pipDelegate = PiPDelegate()
|
var pipDelegate = PiPDelegate()
|
||||||
|
@ -142,7 +142,7 @@ struct ContentView: View {
|
|||||||
.environmentObject(recents)
|
.environmentObject(recents)
|
||||||
.environmentObject(subscriptions)
|
.environmentObject(subscriptions)
|
||||||
.environmentObject(thumbnailsModel)
|
.environmentObject(thumbnailsModel)
|
||||||
.environment(\.navigationStyle, .sidebar)
|
.environment(\.navigationStyle, navigationStyle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ struct PlayerControls: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack(alignment: .topTrailing) {
|
ZStack(alignment: .topLeading) {
|
||||||
VStack {
|
VStack {
|
||||||
ZStack(alignment: .center) {
|
ZStack(alignment: .center) {
|
||||||
OpeningStream()
|
OpeningStream()
|
||||||
@ -39,19 +39,20 @@ struct PlayerControls: View {
|
|||||||
VStack(spacing: 4) {
|
VStack(spacing: 4) {
|
||||||
buttonsBar
|
buttonsBar
|
||||||
|
|
||||||
if let video = player.currentVideo, player.playingFullScreen {
|
HStack {
|
||||||
VStack(alignment: .leading, spacing: 2) {
|
if !player.currentVideo.isNil, player.playingFullScreen {
|
||||||
Text(video.title)
|
Button {
|
||||||
.font(.caption.bold())
|
withAnimation(Self.animation) {
|
||||||
|
model.presentingDetailsOverlay = true
|
||||||
Text(video.author)
|
}
|
||||||
.font(.caption)
|
} label: {
|
||||||
.foregroundColor(.secondary)
|
ControlsBar(fullScreen: $model.presentingDetailsOverlay, presentingControls: false, detailsTogglePlayer: false, detailsToggleFullScreen: false)
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||||
|
.frame(maxWidth: 300, alignment: .leading)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
}
|
}
|
||||||
.padding(4)
|
Spacer()
|
||||||
.modifier(ControlBackgroundModifier())
|
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 2))
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -69,9 +70,6 @@ struct PlayerControls: View {
|
|||||||
.offset(y: -25)
|
.offset(y: -25)
|
||||||
.zIndex(1)
|
.zIndex(1)
|
||||||
}
|
}
|
||||||
#if os(tvOS)
|
|
||||||
.offset(y: -50)
|
|
||||||
#endif
|
|
||||||
.frame(maxWidth: 500)
|
.frame(maxWidth: 500)
|
||||||
.padding(.bottom, 2)
|
.padding(.bottom, 2)
|
||||||
}
|
}
|
||||||
@ -79,7 +77,7 @@ struct PlayerControls: View {
|
|||||||
.padding(.top, 2)
|
.padding(.top, 2)
|
||||||
.padding(.horizontal, 2)
|
.padding(.horizontal, 2)
|
||||||
}
|
}
|
||||||
.opacity(model.presentingControlsOverlay ? 1 : model.presentingControls ? 1 : 0)
|
.opacity(model.presentingOverlays ? 0 : model.presentingControls ? 1 : 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if os(tvOS)
|
#if os(tvOS)
|
||||||
@ -99,11 +97,16 @@ struct PlayerControls: View {
|
|||||||
ControlsOverlay()
|
ControlsOverlay()
|
||||||
.frame(height: overlayHeight)
|
.frame(height: overlayHeight)
|
||||||
.padding()
|
.padding()
|
||||||
.modifier(ControlBackgroundModifier(enabled: true))
|
.modifier(ControlBackgroundModifier())
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 4))
|
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||||
.offset(x: -2, y: 40)
|
|
||||||
.opacity(model.presentingControlsOverlay ? 1 : 0)
|
.opacity(model.presentingControlsOverlay ? 1 : 0)
|
||||||
|
|
||||||
|
VideoDetailsOverlay()
|
||||||
|
.frame(maxWidth: detailsWidth, maxHeight: 450)
|
||||||
|
.modifier(ControlBackgroundModifier())
|
||||||
|
.clipShape(RoundedRectangle(cornerRadius: 4))
|
||||||
|
.opacity(model.presentingDetailsOverlay ? 1 : 0)
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
player.restoreLastSkippedSegment()
|
player.restoreLastSkippedSegment()
|
||||||
} label: {
|
} label: {
|
||||||
@ -124,13 +127,18 @@ struct PlayerControls: View {
|
|||||||
.offset(x: -2, y: -2)
|
.offset(x: -2, y: -2)
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.opacity(model.presentingControls ? 0 : player.lastSkipped.isNil ? 0 : 1)
|
.opacity(model.presentingControls || model.presentingOverlays ? 0 : player.lastSkipped.isNil ? 0 : 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var overlayHeight: Double {
|
var overlayHeight: Double {
|
||||||
guard let player = player, player.playerSize.height.isFinite else { return 0 }
|
guard let player = player, player.playerSize.height.isFinite else { return 0 }
|
||||||
return [0, [player.playerSize.height - 80, 140].min()!].max()!
|
return [0, [player.playerSize.height - 40, 140].min()!].max()!
|
||||||
|
}
|
||||||
|
|
||||||
|
var detailsWidth: Double {
|
||||||
|
guard let player = player, player.playerSize.width.isFinite else { return 200 }
|
||||||
|
return [player.playerSize.width, 600].min()!
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder var controlsBackground: some View {
|
@ViewBuilder var controlsBackground: some View {
|
||||||
|
25
Shared/Player/Controls/VideoDetailsOverlay.swift
Normal file
25
Shared/Player/Controls/VideoDetailsOverlay.swift
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import Defaults
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct VideoDetailsOverlay: View {
|
||||||
|
@EnvironmentObject<PlayerControlsModel> private var controls
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VideoDetails(sidebarQueue: false, fullScreen: fullScreenBinding)
|
||||||
|
}
|
||||||
|
|
||||||
|
var fullScreenBinding: Binding<Bool> {
|
||||||
|
.init(get: {
|
||||||
|
controls.presentingDetailsOverlay
|
||||||
|
}, set: { newValue in
|
||||||
|
controls.presentingDetailsOverlay = newValue
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VideoDetailsOverlay_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
VideoDetailsOverlay()
|
||||||
|
.injectFixtureEnvironmentObjects()
|
||||||
|
}
|
||||||
|
}
|
@ -9,17 +9,7 @@ struct PlayerGestures: View {
|
|||||||
gestureRectangle
|
gestureRectangle
|
||||||
.tapRecognizer(
|
.tapRecognizer(
|
||||||
tapSensitivity: 0.2,
|
tapSensitivity: 0.2,
|
||||||
singleTapAction: {
|
singleTapAction: { singleTapAction() },
|
||||||
if model.presentingControlsOverlay {
|
|
||||||
model.presentingControls = true
|
|
||||||
model.resetTimer()
|
|
||||||
withAnimation(PlayerControls.animation) {
|
|
||||||
model.presentingControlsOverlay = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
model.toggle()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
doubleTapAction: {
|
doubleTapAction: {
|
||||||
player.backend.seek(relative: .secondsInDefaultTimescale(-10))
|
player.backend.seek(relative: .secondsInDefaultTimescale(-10))
|
||||||
},
|
},
|
||||||
@ -31,17 +21,7 @@ struct PlayerGestures: View {
|
|||||||
gestureRectangle
|
gestureRectangle
|
||||||
.tapRecognizer(
|
.tapRecognizer(
|
||||||
tapSensitivity: 0.2,
|
tapSensitivity: 0.2,
|
||||||
singleTapAction: {
|
singleTapAction: { singleTapAction() },
|
||||||
if model.presentingControlsOverlay {
|
|
||||||
model.presentingControls = true
|
|
||||||
model.resetTimer()
|
|
||||||
withAnimation(PlayerControls.animation) {
|
|
||||||
model.presentingControlsOverlay = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
model.toggle()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
doubleTapAction: {
|
doubleTapAction: {
|
||||||
player.backend.togglePlay()
|
player.backend.togglePlay()
|
||||||
},
|
},
|
||||||
@ -53,17 +33,7 @@ struct PlayerGestures: View {
|
|||||||
gestureRectangle
|
gestureRectangle
|
||||||
.tapRecognizer(
|
.tapRecognizer(
|
||||||
tapSensitivity: 0.2,
|
tapSensitivity: 0.2,
|
||||||
singleTapAction: {
|
singleTapAction: { singleTapAction() },
|
||||||
if model.presentingControlsOverlay {
|
|
||||||
model.presentingControls = true
|
|
||||||
model.resetTimer()
|
|
||||||
withAnimation(PlayerControls.animation) {
|
|
||||||
model.presentingControlsOverlay = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
model.toggle()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
doubleTapAction: {
|
doubleTapAction: {
|
||||||
player.backend.seek(relative: .secondsInDefaultTimescale(10))
|
player.backend.seek(relative: .secondsInDefaultTimescale(10))
|
||||||
},
|
},
|
||||||
@ -74,6 +44,16 @@ struct PlayerGestures: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func singleTapAction() {
|
||||||
|
if model.presentingOverlays {
|
||||||
|
withAnimation(PlayerControls.animation) {
|
||||||
|
model.hideOverlays()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
model.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var gestureRectangle: some View {
|
var gestureRectangle: some View {
|
||||||
Color.clear
|
Color.clear
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
|
@ -26,34 +26,32 @@ struct PlayerQueueRow: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Button {
|
||||||
Button {
|
player.prepareCurrentItemForHistory()
|
||||||
player.prepareCurrentItemForHistory()
|
|
||||||
|
|
||||||
player.avPlayerBackend.startPictureInPictureOnPlay = player.playingInPictureInPicture
|
player.avPlayerBackend.startPictureInPictureOnPlay = player.playingInPictureInPicture
|
||||||
|
|
||||||
player.videoBeingOpened = item.video
|
player.videoBeingOpened = item.video
|
||||||
|
|
||||||
if history {
|
if history {
|
||||||
player.playHistory(item, at: watchStoppedAt)
|
player.playHistory(item, at: watchStoppedAt)
|
||||||
} else {
|
} else {
|
||||||
player.advanceToItem(item, at: watchStoppedAt)
|
player.advanceToItem(item, at: watchStoppedAt)
|
||||||
}
|
|
||||||
|
|
||||||
if fullScreen {
|
|
||||||
withAnimation {
|
|
||||||
fullScreen = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if closePiPOnNavigation, player.playingInPictureInPicture {
|
|
||||||
player.closePiP()
|
|
||||||
}
|
|
||||||
} label: {
|
|
||||||
VideoBanner(video: item.video, playbackTime: watchStoppedAt, videoDuration: watch?.videoDuration)
|
|
||||||
}
|
}
|
||||||
.buttonStyle(.plain)
|
|
||||||
|
if fullScreen {
|
||||||
|
withAnimation {
|
||||||
|
fullScreen = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if closePiPOnNavigation, player.playingInPictureInPicture {
|
||||||
|
player.closePiP()
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
VideoBanner(video: item.video, playbackTime: watchStoppedAt, videoDuration: watch?.videoDuration)
|
||||||
}
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var watch: Watch? {
|
private var watch: Watch? {
|
||||||
|
@ -28,9 +28,10 @@ struct PlayerQueueView: View {
|
|||||||
playedPreviously
|
playedPreviously
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.listRowBackground(Color.clear)
|
||||||
#if !os(iOS)
|
#if !os(iOS)
|
||||||
.padding(.vertical, 5)
|
.padding(.vertical, 5)
|
||||||
.listRowInsets(EdgeInsets())
|
.listRowInsets(EdgeInsets())
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +39,8 @@ struct PlayerQueueView: View {
|
|||||||
.listStyle(.inset)
|
.listStyle(.inset)
|
||||||
#elseif os(iOS)
|
#elseif os(iOS)
|
||||||
.listStyle(.grouped)
|
.listStyle(.grouped)
|
||||||
|
.backport
|
||||||
|
.scrollContentBackground(false)
|
||||||
#else
|
#else
|
||||||
.listStyle(.plain)
|
.listStyle(.plain)
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,6 +13,7 @@ struct RelatedView: View {
|
|||||||
Section(header: Text("Related")) {
|
Section(header: Text("Related")) {
|
||||||
ForEach(related) { video in
|
ForEach(related) { video in
|
||||||
PlayerQueueRow(item: PlayerQueueItem(video))
|
PlayerQueueRow(item: PlayerQueueItem(video))
|
||||||
|
.listRowBackground(Color.clear)
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
Section {
|
Section {
|
||||||
Button {
|
Button {
|
||||||
@ -53,6 +54,8 @@ struct RelatedView: View {
|
|||||||
.listStyle(.inset)
|
.listStyle(.inset)
|
||||||
#elseif os(iOS)
|
#elseif os(iOS)
|
||||||
.listStyle(.grouped)
|
.listStyle(.grouped)
|
||||||
|
.backport
|
||||||
|
.scrollContentBackground(false)
|
||||||
#else
|
#else
|
||||||
.listStyle(.plain)
|
.listStyle(.plain)
|
||||||
#endif
|
#endif
|
||||||
|
@ -108,7 +108,6 @@ struct VideoDetails: View {
|
|||||||
page.update(.moveToLast)
|
page.update(.moveToLast)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.edgesIgnoringSafeArea(.horizontal)
|
|
||||||
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
|
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,18 +177,14 @@ struct VideoDetails: View {
|
|||||||
}
|
}
|
||||||
case .chapters:
|
case .chapters:
|
||||||
ChaptersView()
|
ChaptersView()
|
||||||
.edgesIgnoringSafeArea(.horizontal)
|
|
||||||
|
|
||||||
case .queue:
|
case .queue:
|
||||||
PlayerQueueView(sidebarQueue: sidebarQueue, fullScreen: $fullScreen)
|
PlayerQueueView(sidebarQueue: sidebarQueue, fullScreen: $fullScreen)
|
||||||
.edgesIgnoringSafeArea(.horizontal)
|
|
||||||
|
|
||||||
case .related:
|
case .related:
|
||||||
RelatedView()
|
RelatedView()
|
||||||
.edgesIgnoringSafeArea(.horizontal)
|
|
||||||
case .comments:
|
case .comments:
|
||||||
CommentsView(embedInScrollView: true)
|
CommentsView(embedInScrollView: true)
|
||||||
.edgesIgnoringSafeArea(.horizontal)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
@ -209,16 +204,16 @@ struct VideoDetails: View {
|
|||||||
VStack(alignment: .leading, spacing: 10) {
|
VStack(alignment: .leading, spacing: 10) {
|
||||||
if !player.videoBeingOpened.isNil && (video.description.isNil || video.description!.isEmpty) {
|
if !player.videoBeingOpened.isNil && (video.description.isNil || video.description!.isEmpty) {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
ForEach(1 ... Int.random(in: 3 ... 5), id: \.self) { _ in
|
Text(String(repeating: Video.fixture.description ?? "", count: Int.random(in: 1 ... 30)))
|
||||||
Text(String(repeating: Video.fixture.description!, count: Int.random(in: 1 ... 4)))
|
.redacted(reason: .placeholder)
|
||||||
.redacted(reason: .placeholder)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if let description = video.description {
|
} else if let description = video.description {
|
||||||
Group {
|
Group {
|
||||||
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) {
|
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, *) {
|
||||||
Text(description)
|
Text(description)
|
||||||
|
#if !os(tvOS)
|
||||||
.textSelection(.enabled)
|
.textSelection(.enabled)
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
Text(description)
|
Text(description)
|
||||||
}
|
}
|
||||||
|
@ -119,6 +119,7 @@ struct VideoPlayerView: View {
|
|||||||
}
|
}
|
||||||
viewVerticalOffset = Self.hiddenOffset
|
viewVerticalOffset = Self.hiddenOffset
|
||||||
stopOrientationUpdates()
|
stopOrientationUpdates()
|
||||||
|
player.controls.hideOverlays()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -203,9 +204,9 @@ struct VideoPlayerView: View {
|
|||||||
hoveringPlayer = hovering
|
hoveringPlayer = hovering
|
||||||
hovering ? playerControls.show() : playerControls.hide()
|
hovering ? playerControls.show() : playerControls.hide()
|
||||||
}
|
}
|
||||||
#if !os(macOS)
|
#if os(iOS)
|
||||||
.gesture(playerDragGesture)
|
.gesture(isPlayerDragGestureEnabled ? playerDragGesture : nil)
|
||||||
#else
|
#elseif os(macOS)
|
||||||
.onAppear(perform: {
|
.onAppear(perform: {
|
||||||
NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) {
|
NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) {
|
||||||
if !player.currentItem.isNil, hoveringPlayer {
|
if !player.currentItem.isNil, hoveringPlayer {
|
||||||
@ -296,6 +297,9 @@ struct VideoPlayerView: View {
|
|||||||
.onChange(of: proxy.size) { _ in
|
.onChange(of: proxy.size) { _ in
|
||||||
player.playerSize = proxy.size
|
player.playerSize = proxy.size
|
||||||
}
|
}
|
||||||
|
.onChange(of: player.controls.presentingOverlays) { _ in
|
||||||
|
player.playerSize = proxy.size
|
||||||
|
}
|
||||||
})
|
})
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
.padding(.top, player.playingFullScreen && verticalSizeClass == .regular ? 20 : 0)
|
.padding(.top, player.playingFullScreen && verticalSizeClass == .regular ? 20 : 0)
|
||||||
@ -351,6 +355,10 @@ struct VideoPlayerView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isPlayerDragGestureEnabled: Bool {
|
||||||
|
!player.controls.presentingDetailsOverlay && !player.controls.presentingDetailsOverlay
|
||||||
|
}
|
||||||
|
|
||||||
var controlsTopPadding: Double {
|
var controlsTopPadding: Double {
|
||||||
guard fullScreenLayout else { return 0 }
|
guard fullScreenLayout else { return 0 }
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ struct ControlsBar: View {
|
|||||||
var borderBottom = true
|
var borderBottom = true
|
||||||
var detailsTogglePlayer = true
|
var detailsTogglePlayer = true
|
||||||
var detailsToggleFullScreen = false
|
var detailsToggleFullScreen = false
|
||||||
|
var titleLineLimit = 2
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
@ -69,7 +70,9 @@ struct ControlsBar: View {
|
|||||||
details
|
details
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
}
|
}
|
||||||
|
#if !os(tvOS)
|
||||||
.keyboardShortcut("t")
|
.keyboardShortcut("t")
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
details
|
details
|
||||||
}
|
}
|
||||||
@ -139,7 +142,9 @@ struct ControlsBar: View {
|
|||||||
subscriptions.isSubscribing(video.channel.id)
|
subscriptions.isSubscribing(video.channel.id)
|
||||||
{
|
{
|
||||||
Image(systemName: "star.circle.fill")
|
Image(systemName: "star.circle.fill")
|
||||||
|
#if !os(tvOS)
|
||||||
.background(Color.background)
|
.background(Color.background)
|
||||||
|
#endif
|
||||||
.clipShape(Circle())
|
.clipShape(Circle())
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
}
|
}
|
||||||
@ -166,7 +171,9 @@ struct ControlsBar: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareButton(contentItem: .init(video: model.currentVideo))
|
#if !os(tvOS)
|
||||||
|
ShareButton(contentItem: .init(video: model.currentVideo))
|
||||||
|
#endif
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
Button {
|
Button {
|
||||||
@ -215,12 +222,14 @@ struct ControlsBar: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 5) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
Text(model.currentVideo?.title ?? "Not playing")
|
Text(model.currentVideo?.title ?? "Not playing")
|
||||||
.font(.system(size: 14))
|
.font(.system(size: 14))
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
.foregroundColor(model.currentVideo.isNil ? .secondary : .accentColor)
|
.foregroundColor(model.currentVideo.isNil ? .secondary : .accentColor)
|
||||||
.lineLimit(1)
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.lineLimit(titleLineLimit)
|
||||||
|
.multilineTextAlignment(.leading)
|
||||||
|
|
||||||
if let video = model.currentVideo {
|
if let video = model.currentVideo {
|
||||||
HStack(spacing: 2) {
|
HStack(spacing: 2) {
|
||||||
|
@ -714,6 +714,14 @@
|
|||||||
37E70927271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */; };
|
37E70927271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */; };
|
||||||
37E70928271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */; };
|
37E70928271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */; };
|
||||||
37E70929271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */; };
|
37E70929271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */; };
|
||||||
|
37E80F3C287B107F00561799 /* VideoDetailsOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E80F3B287B107F00561799 /* VideoDetailsOverlay.swift */; };
|
||||||
|
37E80F3D287B107F00561799 /* VideoDetailsOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E80F3B287B107F00561799 /* VideoDetailsOverlay.swift */; };
|
||||||
|
37E80F40287B472300561799 /* ScrollContentBackground+Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E80F3F287B472300561799 /* ScrollContentBackground+Backport.swift */; };
|
||||||
|
37E80F43287B7AAF00561799 /* SwiftUIPager in Frameworks */ = {isa = PBXBuildFile; productRef = 37E80F42287B7AAF00561799 /* SwiftUIPager */; };
|
||||||
|
37E80F44287B7AB400561799 /* VideoDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B81AFE26D2CA3700675966 /* VideoDetails.swift */; };
|
||||||
|
37E80F45287B7AC000561799 /* ControlsBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372CFD14285F2E2A00B0B54B /* ControlsBar.swift */; };
|
||||||
|
37E80F46287B7AEC00561799 /* PlayerQueueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CC3F4B270CFE1700608308 /* PlayerQueueView.swift */; };
|
||||||
|
37E80F47287B7B9400561799 /* VideoDetailsOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E80F3B287B107F00561799 /* VideoDetailsOverlay.swift */; };
|
||||||
37E8B0EC27B326C00024006F /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E8B0EB27B326C00024006F /* TimelineView.swift */; };
|
37E8B0EC27B326C00024006F /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E8B0EB27B326C00024006F /* TimelineView.swift */; };
|
||||||
37E8B0ED27B326C00024006F /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E8B0EB27B326C00024006F /* TimelineView.swift */; };
|
37E8B0ED27B326C00024006F /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E8B0EB27B326C00024006F /* TimelineView.swift */; };
|
||||||
37E8B0EE27B326C00024006F /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E8B0EB27B326C00024006F /* TimelineView.swift */; };
|
37E8B0EE27B326C00024006F /* TimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37E8B0EB27B326C00024006F /* TimelineView.swift */; };
|
||||||
@ -1179,6 +1187,8 @@
|
|||||||
37E64DD026D597EB00C71877 /* SubscriptionsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsModel.swift; sourceTree = "<group>"; };
|
37E64DD026D597EB00C71877 /* SubscriptionsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsModel.swift; sourceTree = "<group>"; };
|
||||||
37E70922271CD43000D34DDE /* WelcomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreen.swift; sourceTree = "<group>"; };
|
37E70922271CD43000D34DDE /* WelcomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreen.swift; sourceTree = "<group>"; };
|
||||||
37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenSettingsButton.swift; sourceTree = "<group>"; };
|
37E70926271CDDAE00D34DDE /* OpenSettingsButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenSettingsButton.swift; sourceTree = "<group>"; };
|
||||||
|
37E80F3B287B107F00561799 /* VideoDetailsOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoDetailsOverlay.swift; sourceTree = "<group>"; };
|
||||||
|
37E80F3F287B472300561799 /* ScrollContentBackground+Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ScrollContentBackground+Backport.swift"; sourceTree = "<group>"; };
|
||||||
37E8B0EB27B326C00024006F /* TimelineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimelineView.swift; sourceTree = "<group>"; };
|
37E8B0EB27B326C00024006F /* TimelineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimelineView.swift; sourceTree = "<group>"; };
|
||||||
37E8B0EF27B326F30024006F /* Comparable+Clamped.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Comparable+Clamped.swift"; sourceTree = "<group>"; };
|
37E8B0EF27B326F30024006F /* Comparable+Clamped.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Comparable+Clamped.swift"; sourceTree = "<group>"; };
|
||||||
37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SponsorBlockAPI.swift; sourceTree = "<group>"; };
|
37EAD86A267B9C5600D9E01B /* SponsorBlockAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SponsorBlockAPI.swift; sourceTree = "<group>"; };
|
||||||
@ -1369,6 +1379,7 @@
|
|||||||
3772003A27E8EEBE00CB2475 /* CoreMedia.framework in Frameworks */,
|
3772003A27E8EEBE00CB2475 /* CoreMedia.framework in Frameworks */,
|
||||||
372915E42687E33E00F5A35B /* Defaults in Frameworks */,
|
372915E42687E33E00F5A35B /* Defaults in Frameworks */,
|
||||||
3772003B27E8EEC800CB2475 /* libbz2.tbd in Frameworks */,
|
3772003B27E8EEC800CB2475 /* libbz2.tbd in Frameworks */,
|
||||||
|
37E80F43287B7AAF00561799 /* SwiftUIPager in Frameworks */,
|
||||||
37BADCA9269A570B009BE4FB /* Alamofire in Frameworks */,
|
37BADCA9269A570B009BE4FB /* Alamofire in Frameworks */,
|
||||||
37D4B19D2671817900C925CA /* SwiftyJSON in Frameworks */,
|
37D4B19D2671817900C925CA /* SwiftyJSON in Frameworks */,
|
||||||
3797757D268922D100DD52A8 /* Siesta in Frameworks */,
|
3797757D268922D100DD52A8 /* Siesta in Frameworks */,
|
||||||
@ -1437,6 +1448,7 @@
|
|||||||
37F13B61285E43C000B137E4 /* ControlsOverlay.swift */,
|
37F13B61285E43C000B137E4 /* ControlsOverlay.swift */,
|
||||||
37030FFE27B04DCC00ECDDAA /* PlayerControls.swift */,
|
37030FFE27B04DCC00ECDDAA /* PlayerControls.swift */,
|
||||||
37648B68286CF5F1003D330B /* TVControls.swift */,
|
37648B68286CF5F1003D330B /* TVControls.swift */,
|
||||||
|
37E80F3B287B107F00561799 /* VideoDetailsOverlay.swift */,
|
||||||
);
|
);
|
||||||
path = Controls;
|
path = Controls;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1554,10 +1566,11 @@
|
|||||||
children = (
|
children = (
|
||||||
3722AEBD274DA401005EA4D6 /* Backport.swift */,
|
3722AEBD274DA401005EA4D6 /* Backport.swift */,
|
||||||
3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */,
|
3722AEBB274DA396005EA4D6 /* Badge+Backport.swift */,
|
||||||
3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */,
|
|
||||||
3727B74727872A500021C15E /* VisualEffectBlur-macOS.swift */,
|
|
||||||
3727B74927872A920021C15E /* VisualEffectBlur-iOS.swift */,
|
|
||||||
37136CAB286273060095C0CF /* PersistentSystemOverlays+Backport.swift */,
|
37136CAB286273060095C0CF /* PersistentSystemOverlays+Backport.swift */,
|
||||||
|
37E80F3F287B472300561799 /* ScrollContentBackground+Backport.swift */,
|
||||||
|
3722AEBF274DAEB8005EA4D6 /* Tint+Backport.swift */,
|
||||||
|
3727B74927872A920021C15E /* VisualEffectBlur-iOS.swift */,
|
||||||
|
3727B74727872A500021C15E /* VisualEffectBlur-macOS.swift */,
|
||||||
);
|
);
|
||||||
path = Backports;
|
path = Backports;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2311,6 +2324,7 @@
|
|||||||
3765917D27237D2A009F956E /* PINCache */,
|
3765917D27237D2A009F956E /* PINCache */,
|
||||||
37CF8B8728535E6300B71E37 /* SDWebImage */,
|
37CF8B8728535E6300B71E37 /* SDWebImage */,
|
||||||
372AA411286D06950000B1DC /* Repeat */,
|
372AA411286D06950000B1DC /* Repeat */,
|
||||||
|
37E80F42287B7AAF00561799 /* SwiftUIPager */,
|
||||||
);
|
);
|
||||||
productName = Yattee;
|
productName = Yattee;
|
||||||
productReference = 37D4B158267164AE00C925CA /* Yattee.app */;
|
productReference = 37D4B158267164AE00C925CA /* Yattee.app */;
|
||||||
@ -2674,6 +2688,7 @@
|
|||||||
378E50FF26FE8EEE00F49626 /* AccountsMenuView.swift in Sources */,
|
378E50FF26FE8EEE00F49626 /* AccountsMenuView.swift in Sources */,
|
||||||
37169AA62729E2CC0011DE61 /* AccountsBridge.swift in Sources */,
|
37169AA62729E2CC0011DE61 /* AccountsBridge.swift in Sources */,
|
||||||
37C7A1DA267CACF50010EAD6 /* TrendingCountry.swift in Sources */,
|
37C7A1DA267CACF50010EAD6 /* TrendingCountry.swift in Sources */,
|
||||||
|
37E80F40287B472300561799 /* ScrollContentBackground+Backport.swift in Sources */,
|
||||||
3727B74A27872A920021C15E /* VisualEffectBlur-iOS.swift in Sources */,
|
3727B74A27872A920021C15E /* VisualEffectBlur-iOS.swift in Sources */,
|
||||||
37977583268922F600DD52A8 /* InvidiousAPI.swift in Sources */,
|
37977583268922F600DD52A8 /* InvidiousAPI.swift in Sources */,
|
||||||
37130A5F277657300033018A /* PersistenceController.swift in Sources */,
|
37130A5F277657300033018A /* PersistenceController.swift in Sources */,
|
||||||
@ -2836,6 +2851,7 @@
|
|||||||
37BD07BB2698AB60003EBB87 /* AppSidebarNavigation.swift in Sources */,
|
37BD07BB2698AB60003EBB87 /* AppSidebarNavigation.swift in Sources */,
|
||||||
37C0697A2725C09E00F7F6CB /* PlayerQueueItemBridge.swift in Sources */,
|
37C0697A2725C09E00F7F6CB /* PlayerQueueItemBridge.swift in Sources */,
|
||||||
379B0253287A1CDF001015B5 /* OrientationTracker.swift in Sources */,
|
379B0253287A1CDF001015B5 /* OrientationTracker.swift in Sources */,
|
||||||
|
37E80F3C287B107F00561799 /* VideoDetailsOverlay.swift in Sources */,
|
||||||
370B79C9286279810045DB77 /* NSObject+Swizzle.swift in Sources */,
|
370B79C9286279810045DB77 /* NSObject+Swizzle.swift in Sources */,
|
||||||
37D4B0E42671614900C925CA /* YatteeApp.swift in Sources */,
|
37D4B0E42671614900C925CA /* YatteeApp.swift in Sources */,
|
||||||
37C3A241272359900087A57A /* Double+Format.swift in Sources */,
|
37C3A241272359900087A57A /* Double+Format.swift in Sources */,
|
||||||
@ -2886,6 +2902,7 @@
|
|||||||
374C053C2724614F009BDDBE /* PlayerTVMenu.swift in Sources */,
|
374C053C2724614F009BDDBE /* PlayerTVMenu.swift in Sources */,
|
||||||
377FC7DD267A081A00A6BBAF /* PopularView.swift in Sources */,
|
377FC7DD267A081A00A6BBAF /* PopularView.swift in Sources */,
|
||||||
3784CDE327772EE40055BBF2 /* Watch.swift in Sources */,
|
3784CDE327772EE40055BBF2 /* Watch.swift in Sources */,
|
||||||
|
37E80F3D287B107F00561799 /* VideoDetailsOverlay.swift in Sources */,
|
||||||
37DD9DBB2785D60300539416 /* FramePreferenceKey.swift in Sources */,
|
37DD9DBB2785D60300539416 /* FramePreferenceKey.swift in Sources */,
|
||||||
375DFB5926F9DA010013F468 /* InstancesModel.swift in Sources */,
|
375DFB5926F9DA010013F468 /* InstancesModel.swift in Sources */,
|
||||||
3705B183267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
3705B183267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
||||||
@ -3159,6 +3176,7 @@
|
|||||||
37732FF22703A26300F04329 /* AccountValidationStatus.swift in Sources */,
|
37732FF22703A26300F04329 /* AccountValidationStatus.swift in Sources */,
|
||||||
3756C2AC2861151C00E4B059 /* NetworkStateModel.swift in Sources */,
|
3756C2AC2861151C00E4B059 /* NetworkStateModel.swift in Sources */,
|
||||||
37A5DBCA285E371400CA4DD1 /* ControlBackgroundModifier.swift in Sources */,
|
37A5DBCA285E371400CA4DD1 /* ControlBackgroundModifier.swift in Sources */,
|
||||||
|
37E80F46287B7AEC00561799 /* PlayerQueueView.swift in Sources */,
|
||||||
37C0698427260B2100F7F6CB /* ThumbnailsModel.swift in Sources */,
|
37C0698427260B2100F7F6CB /* ThumbnailsModel.swift in Sources */,
|
||||||
37666BAA27023AF000F869E5 /* AccountSelectionView.swift in Sources */,
|
37666BAA27023AF000F869E5 /* AccountSelectionView.swift in Sources */,
|
||||||
3765788B2685471400D4EA09 /* Playlist.swift in Sources */,
|
3765788B2685471400D4EA09 /* Playlist.swift in Sources */,
|
||||||
@ -3168,6 +3186,8 @@
|
|||||||
3752069B285E8DD300CA655F /* Chapter.swift in Sources */,
|
3752069B285E8DD300CA655F /* Chapter.swift in Sources */,
|
||||||
37B044B926F7AB9000E1419D /* SettingsView.swift in Sources */,
|
37B044B926F7AB9000E1419D /* SettingsView.swift in Sources */,
|
||||||
3743B86A27216D3600261544 /* ChannelCell.swift in Sources */,
|
3743B86A27216D3600261544 /* ChannelCell.swift in Sources */,
|
||||||
|
37E80F47287B7B9400561799 /* VideoDetailsOverlay.swift in Sources */,
|
||||||
|
37E80F44287B7AB400561799 /* VideoDetails.swift in Sources */,
|
||||||
3751BA8527E6914F007B1A60 /* ReturnYouTubeDislikeAPI.swift in Sources */,
|
3751BA8527E6914F007B1A60 /* ReturnYouTubeDislikeAPI.swift in Sources */,
|
||||||
37030FFD27B0398000ECDDAA /* MPVClient.swift in Sources */,
|
37030FFD27B0398000ECDDAA /* MPVClient.swift in Sources */,
|
||||||
37B767DD2677C3CA0098BAA8 /* PlayerModel.swift in Sources */,
|
37B767DD2677C3CA0098BAA8 /* PlayerModel.swift in Sources */,
|
||||||
@ -3180,6 +3200,7 @@
|
|||||||
371B7E682759786B00D21217 /* Comment+Fixtures.swift in Sources */,
|
371B7E682759786B00D21217 /* Comment+Fixtures.swift in Sources */,
|
||||||
37BE0BD126A0E2D50092E2DB /* VideoPlayerView.swift in Sources */,
|
37BE0BD126A0E2D50092E2DB /* VideoPlayerView.swift in Sources */,
|
||||||
37AAF27E26737323007FC770 /* PopularView.swift in Sources */,
|
37AAF27E26737323007FC770 /* PopularView.swift in Sources */,
|
||||||
|
37E80F45287B7AC000561799 /* ControlsBar.swift in Sources */,
|
||||||
3743CA50270EFE3400E4D32B /* PlayerQueueRow.swift in Sources */,
|
3743CA50270EFE3400E4D32B /* PlayerQueueRow.swift in Sources */,
|
||||||
376BE50827347B57009AD608 /* SettingsHeader.swift in Sources */,
|
376BE50827347B57009AD608 /* SettingsHeader.swift in Sources */,
|
||||||
37A9966026D6F9B9006E3224 /* FavoritesView.swift in Sources */,
|
37A9966026D6F9B9006E3224 /* FavoritesView.swift in Sources */,
|
||||||
@ -3900,7 +3921,7 @@
|
|||||||
37D4B178267164B000C925CA /* Debug */ = {
|
37D4B178267164B000C925CA /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 71;
|
CURRENT_PROJECT_VERSION = 71;
|
||||||
@ -3909,7 +3930,6 @@
|
|||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = tvOS/Info.plist;
|
INFOPLIST_FILE = tvOS/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Yattee;
|
|
||||||
INFOPLIST_KEY_CFBundleName = "Yattee (Apple TV)";
|
INFOPLIST_KEY_CFBundleName = "Yattee (Apple TV)";
|
||||||
INFOPLIST_KEY_CFBundleVersion = 1;
|
INFOPLIST_KEY_CFBundleVersion = 1;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
@ -3938,7 +3958,7 @@
|
|||||||
37D4B179267164B000C925CA /* Release */ = {
|
37D4B179267164B000C925CA /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image";
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 71;
|
CURRENT_PROJECT_VERSION = 71;
|
||||||
@ -3947,7 +3967,6 @@
|
|||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = tvOS/Info.plist;
|
INFOPLIST_FILE = tvOS/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Yattee;
|
|
||||||
INFOPLIST_KEY_CFBundleName = "Yattee (Apple TV)";
|
INFOPLIST_KEY_CFBundleName = "Yattee (Apple TV)";
|
||||||
INFOPLIST_KEY_CFBundleVersion = 1;
|
INFOPLIST_KEY_CFBundleVersion = 1;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
@ -4470,6 +4489,11 @@
|
|||||||
package = 37D4B19B2671817900C925CA /* XCRemoteSwiftPackageReference "SwiftyJSON" */;
|
package = 37D4B19B2671817900C925CA /* XCRemoteSwiftPackageReference "SwiftyJSON" */;
|
||||||
productName = SwiftyJSON;
|
productName = SwiftyJSON;
|
||||||
};
|
};
|
||||||
|
37E80F42287B7AAF00561799 /* SwiftUIPager */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 37A5DBC2285DFF5400CA4DD1 /* XCRemoteSwiftPackageReference "SwiftUIPager" */;
|
||||||
|
productName = SwiftUIPager;
|
||||||
|
};
|
||||||
37FB28452722054C00A57617 /* SDWebImageSwiftUI */ = {
|
37FB28452722054C00A57617 /* SDWebImageSwiftUI */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 37FB28442722054B00A57617 /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */;
|
package = 37FB28442722054B00A57617 /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */;
|
||||||
|
Loading…
Reference in New Issue
Block a user