add jump forward/backward indicators tvos

This commit is contained in:
Ethan Pippin 2022-01-01 21:17:22 -07:00
parent 1d2ed589c1
commit 29e824a035
4 changed files with 119 additions and 9 deletions

View File

@ -28,5 +28,8 @@ protocol PlayerOverlayDelegate {
func didSelectAudioStream(index: Int)
func didSelectSubtitleStream(index: Int)
func didSelectPreviousItem()
func didSelectNextItem()
func didFocusOnButton()
}

View File

@ -53,6 +53,8 @@ class VLCPlayerViewController: UIViewController {
}
private lazy var videoContentView = makeVideoContentView()
private lazy var jumpBackwardOverlayView = makeJumpBackwardOverlayView()
private lazy var jumpForwardOverlayView = makeJumpForwardOverlayView()
private var currentOverlayHostingController: UIHostingController<tvOSVLCOverlay>?
private var currentOverlayContentHostingController: UIHostingController<tvOSOverlayContentView>?
@ -73,6 +75,11 @@ class VLCPlayerViewController: UIViewController {
private func setupSubviews() {
view.addSubview(videoContentView)
view.addSubview(jumpForwardOverlayView)
view.addSubview(jumpBackwardOverlayView)
jumpBackwardOverlayView.alpha = 0
jumpForwardOverlayView.alpha = 0
}
private func setupConstraints() {
@ -82,6 +89,14 @@ class VLCPlayerViewController: UIViewController {
videoContentView.leftAnchor.constraint(equalTo: view.leftAnchor),
videoContentView.rightAnchor.constraint(equalTo: view.rightAnchor)
])
NSLayoutConstraint.activate([
jumpBackwardOverlayView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 300),
jumpBackwardOverlayView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
NSLayoutConstraint.activate([
jumpForwardOverlayView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -300),
jumpForwardOverlayView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
// MARK: viewWillDisappear
@ -119,12 +134,27 @@ class VLCPlayerViewController: UIViewController {
setupLeftSwipedGestureRecognizer()
setupPanGestureRecognizer()
let menuPressRecognizer = UITapGestureRecognizer()
menuPressRecognizer.addTarget(self, action: #selector(menuButtonAction))
menuPressRecognizer.allowedPressTypes = [NSNumber(value: UIPress.PressType.menu.rawValue)]
view.addGestureRecognizer(menuPressRecognizer)
let defaultNotificationCenter = NotificationCenter.default
defaultNotificationCenter.addObserver(self, selector: #selector(appWillTerminate), name: UIApplication.willTerminateNotification, object: nil)
defaultNotificationCenter.addObserver(self, selector: #selector(appWillResignActive), name: UIApplication.willResignActiveNotification, object: nil)
defaultNotificationCenter.addObserver(self, selector: #selector(appWillResignActive), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
@objc private func menuButtonAction() {
if displayingOverlay {
hideOverlay()
} else {
vlcMediaPlayer.pause()
dismiss(animated: true, completion: nil)
}
}
@objc private func appWillTerminate() {
viewModel.sendStopReport()
}
@ -155,6 +185,24 @@ class VLCPlayerViewController: UIViewController {
return view
}
private func makeJumpBackwardOverlayView() -> UIImageView {
let symbolConfig = UIImage.SymbolConfiguration(pointSize: 56)
let forwardSymbolImage = UIImage(systemName: jumpBackwardLength.forwardImageLabel, withConfiguration: symbolConfig)
let imageView = UIImageView(image: forwardSymbolImage)
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}
private func makeJumpForwardOverlayView() -> UIImageView {
let symbolConfig = UIImage.SymbolConfiguration(pointSize: 56)
let forwardSymbolImage = UIImage(systemName: jumpForwardLength.forwardImageLabel, withConfiguration: symbolConfig)
let imageView = UIImageView(image: forwardSymbolImage)
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}
// MARK: pressesBegan
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
guard let buttonPress = presses.first?.type else { return }
@ -442,6 +490,42 @@ extension VLCPlayerViewController {
}
}
// MARK: Show/Hide Jump
extension VLCPlayerViewController {
private func flashJumpBackwardOverlay() {
jumpBackwardOverlayView.layer.removeAllAnimations()
UIView.animate(withDuration: 0.1) {
self.jumpBackwardOverlayView.alpha = 1
} completion: { _ in
self.hideJumpBackwardOverlay()
}
}
private func hideJumpBackwardOverlay() {
UIView.animate(withDuration: 0.3) {
self.jumpBackwardOverlayView.alpha = 0
}
}
private func flashJumpFowardOverlay() {
jumpForwardOverlayView.layer.removeAllAnimations()
UIView.animate(withDuration: 0.1) {
self.jumpForwardOverlayView.alpha = 1
} completion: { _ in
self.hideJumpForwardOverlay()
}
}
private func hideJumpForwardOverlay() {
UIView.animate(withDuration: 0.3) {
self.jumpForwardOverlayView.alpha = 0
}
}
}
// MARK: OverlayTimer
extension VLCPlayerViewController {
@ -579,6 +663,8 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
}
func didSelectBackward() {
flashJumpBackwardOverlay()
vlcMediaPlayer.jumpBackward(jumpBackwardLength.rawValue)
restartOverlayDismissTimer()
@ -589,6 +675,8 @@ extension VLCPlayerViewController: PlayerOverlayDelegate {
}
func didSelectForward() {
flashJumpFowardOverlay()
vlcMediaPlayer.jumpForward(jumpForwardLength.rawValue)
restartOverlayDismissTimer()

View File

@ -45,7 +45,7 @@ struct tvOSVLCOverlay: View {
if let subtitle = viewModel.subtitle {
Text(subtitle)
.font(.subheadline)
.foregroundColor(.secondarySystemFill)
.foregroundColor(.lightGray)
}
Text(viewModel.title)
@ -55,16 +55,34 @@ struct tvOSVLCOverlay: View {
Spacer()
if viewModel.subtitlesEnabled {
SFSymbolButton(systemName: "captions.bubble.fill") {
viewModel.playerOverlayDelegate?.didSelectCaptions()
}
if viewModel.showAdjacentItems {
SFSymbolButton(systemName: "chevron.left.circle", action: {
viewModel.playerOverlayDelegate?.didSelectPreviousItem()
})
.frame(maxWidth: 30, maxHeight: 30)
} else {
SFSymbolButton(systemName: "captions.bubble") {
viewModel.playerOverlayDelegate?.didSelectCaptions()
}
.disabled(viewModel.previousItemVideoPlayerViewModel == nil)
.foregroundColor(viewModel.nextItemVideoPlayerViewModel == nil ? .gray : .white)
SFSymbolButton(systemName: "chevron.right.circle", action: {
viewModel.playerOverlayDelegate?.didSelectNextItem()
})
.frame(maxWidth: 30, maxHeight: 30)
.disabled(viewModel.nextItemVideoPlayerViewModel == nil)
.foregroundColor(viewModel.nextItemVideoPlayerViewModel == nil ? .gray : .white)
}
if !viewModel.subtitleStreams.isEmpty {
if viewModel.subtitlesEnabled {
SFSymbolButton(systemName: "captions.bubble.fill") {
viewModel.playerOverlayDelegate?.didSelectCaptions()
}
.frame(maxWidth: 30, maxHeight: 30)
} else {
SFSymbolButton(systemName: "captions.bubble") {
viewModel.playerOverlayDelegate?.didSelectCaptions()
}
.frame(maxWidth: 30, maxHeight: 30)
}
}
SFSymbolButton(systemName: "ellipsis.circle") {

View File

@ -17,6 +17,7 @@ extension Color {
public static let systemFill = Color(UIColor.white)
public static let secondarySystemFill = Color(UIColor.gray)
public static let tertiarySystemFill = Color(UIColor.black)
public static let lightGray = Color(UIColor.lightGray)
#else
public static let systemFill = Color(UIColor.systemFill)
public static let secondarySystemFill = Color(UIColor.secondarySystemBackground)