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