mirror of
https://github.com/yattee/yattee.git
synced 2025-08-05 18:24:02 +00:00
Minor tvOS controls and remote improvements
This commit is contained in:
@@ -70,7 +70,7 @@ struct PlayerControls: View {
|
||||
.zIndex(1)
|
||||
}
|
||||
#if os(tvOS)
|
||||
.offset(y: -100)
|
||||
.offset(y: -50)
|
||||
#endif
|
||||
.frame(maxWidth: 500)
|
||||
.padding(.bottom, 2)
|
||||
|
77
Shared/Player/Controls/TVControls.swift
Normal file
77
Shared/Player/Controls/TVControls.swift
Normal file
@@ -0,0 +1,77 @@
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
struct TVControls: UIViewRepresentable {
|
||||
var model: PlayerControlsModel!
|
||||
var player: PlayerModel!
|
||||
var thumbnails: ThumbnailsModel!
|
||||
|
||||
@State private var direction = ""
|
||||
@State private var controlsArea = UIView()
|
||||
|
||||
func makeUIView(context: Context) -> UIView {
|
||||
let tapGesture = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap(sender:)))
|
||||
|
||||
let leftSwipe = UISwipeGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleSwipe(sender:)))
|
||||
leftSwipe.direction = .left
|
||||
|
||||
let rightSwipe = UISwipeGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleSwipe(sender:)))
|
||||
rightSwipe.direction = .right
|
||||
|
||||
let upSwipe = UISwipeGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleSwipe(sender:)))
|
||||
upSwipe.direction = .up
|
||||
|
||||
let downSwipe = UISwipeGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleSwipe(sender:)))
|
||||
downSwipe.direction = .down
|
||||
|
||||
controlsArea.addGestureRecognizer(tapGesture)
|
||||
controlsArea.addGestureRecognizer(leftSwipe)
|
||||
controlsArea.addGestureRecognizer(rightSwipe)
|
||||
controlsArea.addGestureRecognizer(upSwipe)
|
||||
controlsArea.addGestureRecognizer(downSwipe)
|
||||
|
||||
let controls = UIHostingController(rootView: PlayerControls(player: player, thumbnails: thumbnails))
|
||||
controls.view.frame = .init(
|
||||
origin: .zero,
|
||||
size: .init(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
|
||||
)
|
||||
|
||||
controlsArea.addSubview(controls.view)
|
||||
|
||||
return controlsArea
|
||||
}
|
||||
|
||||
func updateUIView(_: UIView, context _: Context) {}
|
||||
|
||||
func makeCoordinator() -> TVControls.Coordinator {
|
||||
Coordinator(controlsArea, model: model)
|
||||
}
|
||||
|
||||
final class Coordinator: NSObject {
|
||||
private let view: UIView
|
||||
private let model: PlayerControlsModel
|
||||
|
||||
init(_ view: UIView, model: PlayerControlsModel) {
|
||||
self.view = view
|
||||
self.model = model
|
||||
super.init()
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder _: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@objc func handleTap(sender: UITapGestureRecognizer) {
|
||||
let location = sender.location(in: view)
|
||||
model.reporter.send("tap \(location)")
|
||||
print("tap \(location)")
|
||||
}
|
||||
|
||||
@objc func handleSwipe(sender: UISwipeGestureRecognizer) {
|
||||
let location = sender.location(in: view)
|
||||
model.reporter.send("swipe \(location)")
|
||||
print("swipe \(location)")
|
||||
}
|
||||
}
|
||||
}
|
@@ -138,29 +138,39 @@ struct VideoPlayerView: View {
|
||||
Group {
|
||||
ZStack(alignment: .bottomLeading) {
|
||||
#if os(tvOS)
|
||||
playerView
|
||||
.ignoresSafeArea(.all, edges: .all)
|
||||
.onMoveCommand { direction in
|
||||
if direction == .up || direction == .down {
|
||||
playerControls.show()
|
||||
}
|
||||
ZStack {
|
||||
playerView
|
||||
|
||||
playerControls.resetTimer()
|
||||
|
||||
guard !playerControls.presentingControls else {
|
||||
return
|
||||
}
|
||||
|
||||
if direction == .left {
|
||||
player.backend.seek(relative: .secondsInDefaultTimescale(-10))
|
||||
}
|
||||
if direction == .right {
|
||||
player.backend.seek(relative: .secondsInDefaultTimescale(10))
|
||||
}
|
||||
tvControls
|
||||
}
|
||||
.ignoresSafeArea(.all, edges: .all)
|
||||
.onMoveCommand { direction in
|
||||
if direction == .up || direction == .down {
|
||||
playerControls.show()
|
||||
}
|
||||
.onPlayPauseCommand {
|
||||
player.togglePlay()
|
||||
|
||||
playerControls.resetTimer()
|
||||
|
||||
guard !playerControls.presentingControls else { return }
|
||||
|
||||
if direction == .left {
|
||||
player.backend.seek(relative: .secondsInDefaultTimescale(-10))
|
||||
}
|
||||
if direction == .right {
|
||||
player.backend.seek(relative: .secondsInDefaultTimescale(10))
|
||||
}
|
||||
}
|
||||
.onPlayPauseCommand {
|
||||
player.togglePlay()
|
||||
}
|
||||
|
||||
.onExitCommand {
|
||||
if playerControls.presentingControls {
|
||||
playerControls.hide()
|
||||
} else {
|
||||
player.hide()
|
||||
}
|
||||
}
|
||||
#else
|
||||
GeometryReader { geometry in
|
||||
VStack(spacing: 0) {
|
||||
@@ -308,9 +318,8 @@ struct VideoPlayerView: View {
|
||||
|
||||
#if !os(tvOS)
|
||||
PlayerGestures()
|
||||
PlayerControls(player: player, thumbnails: thumbnails)
|
||||
#endif
|
||||
|
||||
PlayerControls(player: player, thumbnails: thumbnails)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,6 +511,16 @@ struct VideoPlayerView: View {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if os(tvOS)
|
||||
var tvControls: some View {
|
||||
TVControls(model: playerControls, player: player, thumbnails: thumbnails)
|
||||
.onReceive(playerControls.reporter) { _ in
|
||||
playerControls.show()
|
||||
playerControls.resetTimer()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct VideoPlayerView_Previews: PreviewProvider {
|
||||
|
Reference in New Issue
Block a user