add system control gestures (brightness, volume)
This commit is contained in:
parent
5609d4c3ea
commit
682f79631c
|
@ -378,6 +378,8 @@ internal enum L10n {
|
||||||
internal static var switchUser: String { return L10n.tr("Localizable", "switchUser") }
|
internal static var switchUser: String { return L10n.tr("Localizable", "switchUser") }
|
||||||
/// System
|
/// System
|
||||||
internal static var system: String { return L10n.tr("Localizable", "system") }
|
internal static var system: String { return L10n.tr("Localizable", "system") }
|
||||||
|
/// System Control Gestures Enabled
|
||||||
|
internal static var systemControlGesturesEnabled: String { return L10n.tr("Localizable", "systemControlGesturesEnabled") }
|
||||||
/// Tags
|
/// Tags
|
||||||
internal static var tags: String { return L10n.tr("Localizable", "tags") }
|
internal static var tags: String { return L10n.tr("Localizable", "tags") }
|
||||||
/// Too Many Redirects
|
/// Too Many Redirects
|
||||||
|
|
|
@ -46,6 +46,8 @@ extension Defaults.Keys {
|
||||||
// Video player / overlay settings
|
// Video player / overlay settings
|
||||||
static let overlayType = Key<OverlayType>("overlayType", default: .normal, suite: SwiftfinStore.Defaults.generalSuite)
|
static let overlayType = Key<OverlayType>("overlayType", default: .normal, suite: SwiftfinStore.Defaults.generalSuite)
|
||||||
static let jumpGesturesEnabled = Key<Bool>("gesturesEnabled", default: true, suite: SwiftfinStore.Defaults.generalSuite)
|
static let jumpGesturesEnabled = Key<Bool>("gesturesEnabled", default: true, suite: SwiftfinStore.Defaults.generalSuite)
|
||||||
|
static let systemControlGesturesEnabled = Key<Bool>("systemControlGesturesEnabled", default: true,
|
||||||
|
suite: SwiftfinStore.Defaults.generalSuite)
|
||||||
static let videoPlayerJumpForward = Key<VideoPlayerJumpLength>("videoPlayerJumpForward", default: .fifteen,
|
static let videoPlayerJumpForward = Key<VideoPlayerJumpLength>("videoPlayerJumpForward", default: .fifteen,
|
||||||
suite: SwiftfinStore.Defaults.generalSuite)
|
suite: SwiftfinStore.Defaults.generalSuite)
|
||||||
static let videoPlayerJumpBackward = Key<VideoPlayerJumpLength>("videoPlayerJumpBackward", default: .fifteen,
|
static let videoPlayerJumpBackward = Key<VideoPlayerJumpLength>("videoPlayerJumpBackward", default: .fifteen,
|
||||||
|
|
|
@ -115,6 +115,7 @@ final class VideoPlayerViewModel: ViewModel {
|
||||||
let chapters: [ChapterInfo]
|
let chapters: [ChapterInfo]
|
||||||
let overlayType: OverlayType
|
let overlayType: OverlayType
|
||||||
let jumpGesturesEnabled: Bool
|
let jumpGesturesEnabled: Bool
|
||||||
|
let systemControlGesturesEnabled: Bool
|
||||||
let resumeOffset: Bool
|
let resumeOffset: Bool
|
||||||
let streamType: ServerStreamType
|
let streamType: ServerStreamType
|
||||||
let container: String
|
let container: String
|
||||||
|
@ -241,6 +242,7 @@ final class VideoPlayerViewModel: ViewModel {
|
||||||
self.jumpBackwardLength = Defaults[.videoPlayerJumpBackward]
|
self.jumpBackwardLength = Defaults[.videoPlayerJumpBackward]
|
||||||
self.jumpForwardLength = Defaults[.videoPlayerJumpForward]
|
self.jumpForwardLength = Defaults[.videoPlayerJumpForward]
|
||||||
self.jumpGesturesEnabled = Defaults[.jumpGesturesEnabled]
|
self.jumpGesturesEnabled = Defaults[.jumpGesturesEnabled]
|
||||||
|
self.systemControlGesturesEnabled = Defaults[.systemControlGesturesEnabled]
|
||||||
self.shouldShowJumpButtonsInOverlayMenu = Defaults[.shouldShowJumpButtonsInOverlayMenu]
|
self.shouldShowJumpButtonsInOverlayMenu = Defaults[.shouldShowJumpButtonsInOverlayMenu]
|
||||||
|
|
||||||
self.resumeOffset = Defaults[.resumeOffset]
|
self.resumeOffset = Defaults[.resumeOffset]
|
||||||
|
|
|
@ -38,6 +38,8 @@ struct SettingsView: View {
|
||||||
var jumpBackwardLength
|
var jumpBackwardLength
|
||||||
@Default(.jumpGesturesEnabled)
|
@Default(.jumpGesturesEnabled)
|
||||||
var jumpGesturesEnabled
|
var jumpGesturesEnabled
|
||||||
|
@Default(.systemControlGesturesEnabled)
|
||||||
|
var systemControlGesturesEnabled
|
||||||
@Default(.resumeOffset)
|
@Default(.resumeOffset)
|
||||||
var resumeOffset
|
var resumeOffset
|
||||||
@Default(.subtitleSize)
|
@Default(.subtitleSize)
|
||||||
|
@ -107,6 +109,8 @@ struct SettingsView: View {
|
||||||
|
|
||||||
Toggle(L10n.jumpGesturesEnabled, isOn: $jumpGesturesEnabled)
|
Toggle(L10n.jumpGesturesEnabled, isOn: $jumpGesturesEnabled)
|
||||||
|
|
||||||
|
Toggle(L10n.systemControlGesturesEnabled, isOn: $systemControlGesturesEnabled)
|
||||||
|
|
||||||
Toggle(L10n.resume5SecondOffset, isOn: $resumeOffset)
|
Toggle(L10n.resume5SecondOffset, isOn: $resumeOffset)
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
|
|
|
@ -42,12 +42,18 @@ class VLCPlayerViewController: UIViewController {
|
||||||
currentChapterOverlayHostingController?.view.alpha ?? 0 > 0
|
currentChapterOverlayHostingController?.view.alpha ?? 0 > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var panBeganBrightness = CGFloat.zero
|
||||||
|
private var panBeganVolumeValue = Float.zero
|
||||||
|
private var panBeganPoint = CGPoint.zero
|
||||||
|
|
||||||
private lazy var videoContentView = makeVideoContentView()
|
private lazy var videoContentView = makeVideoContentView()
|
||||||
private lazy var mainGestureView = makeMainGestureView()
|
private lazy var mainGestureView = makeMainGestureView()
|
||||||
private var currentOverlayHostingController: UIHostingController<VLCPlayerOverlayView>?
|
private var currentOverlayHostingController: UIHostingController<VLCPlayerOverlayView>?
|
||||||
private var currentChapterOverlayHostingController: UIHostingController<VLCPlayerChapterOverlayView>?
|
private var currentChapterOverlayHostingController: UIHostingController<VLCPlayerChapterOverlayView>?
|
||||||
|
private var systemControlOverlayLabel = UILabel()
|
||||||
private var currentJumpBackwardOverlayView: UIImageView?
|
private var currentJumpBackwardOverlayView: UIImageView?
|
||||||
private var currentJumpForwardOverlayView: UIImageView?
|
private var currentJumpForwardOverlayView: UIImageView?
|
||||||
|
private var volumeView = MPVolumeView()
|
||||||
|
|
||||||
override var keyCommands: [UIKeyCommand]? {
|
override var keyCommands: [UIKeyCommand]? {
|
||||||
var commands = [
|
var commands = [
|
||||||
|
@ -95,6 +101,12 @@ class VLCPlayerViewController: UIViewController {
|
||||||
private func setupSubviews() {
|
private func setupSubviews() {
|
||||||
view.addSubview(videoContentView)
|
view.addSubview(videoContentView)
|
||||||
view.addSubview(mainGestureView)
|
view.addSubview(mainGestureView)
|
||||||
|
|
||||||
|
// Setup BrightnessOverlayView
|
||||||
|
systemControlOverlayLabel.alpha = 0
|
||||||
|
systemControlOverlayLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
systemControlOverlayLabel.font = .systemFont(ofSize: 48)
|
||||||
|
view.addSubview(systemControlOverlayLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupConstraints() {
|
private func setupConstraints() {
|
||||||
|
@ -110,6 +122,10 @@ class VLCPlayerViewController: UIViewController {
|
||||||
mainGestureView.leftAnchor.constraint(equalTo: videoContentView.leftAnchor),
|
mainGestureView.leftAnchor.constraint(equalTo: videoContentView.leftAnchor),
|
||||||
mainGestureView.rightAnchor.constraint(equalTo: videoContentView.rightAnchor),
|
mainGestureView.rightAnchor.constraint(equalTo: videoContentView.rightAnchor),
|
||||||
])
|
])
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
systemControlOverlayLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
|
||||||
|
systemControlOverlayLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: viewWillDisappear
|
// MARK: viewWillDisappear
|
||||||
|
@ -202,6 +218,8 @@ class VLCPlayerViewController: UIViewController {
|
||||||
|
|
||||||
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(didPinch(_:)))
|
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(didPinch(_:)))
|
||||||
|
|
||||||
|
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(didPan(_:)))
|
||||||
|
|
||||||
view.addGestureRecognizer(singleTapGesture)
|
view.addGestureRecognizer(singleTapGesture)
|
||||||
view.addGestureRecognizer(pinchGesture)
|
view.addGestureRecognizer(pinchGesture)
|
||||||
|
|
||||||
|
@ -210,6 +228,10 @@ class VLCPlayerViewController: UIViewController {
|
||||||
view.addGestureRecognizer(leftSwipeGesture)
|
view.addGestureRecognizer(leftSwipeGesture)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if viewModel.systemControlGesturesEnabled {
|
||||||
|
view.addGestureRecognizer(panGesture)
|
||||||
|
}
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +265,35 @@ class VLCPlayerViewController: UIViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc
|
||||||
|
private func didPan(_ gestureRecognizer: UIPanGestureRecognizer) {
|
||||||
|
switch gestureRecognizer.state {
|
||||||
|
case .began:
|
||||||
|
panBeganBrightness = UIScreen.main.brightness
|
||||||
|
if let view = volumeView.subviews.first as? UISlider {
|
||||||
|
panBeganVolumeValue = view.value
|
||||||
|
}
|
||||||
|
panBeganPoint = gestureRecognizer.location(in: mainGestureView)
|
||||||
|
case .changed:
|
||||||
|
let mainGestureViewHalfWidth = mainGestureView.frame.width * 0.5
|
||||||
|
let mainGestureViewHalfHeight = mainGestureView.frame.height * 0.5
|
||||||
|
|
||||||
|
let pos = gestureRecognizer.location(in: mainGestureView)
|
||||||
|
let moveDelta = pos.y - panBeganPoint.y
|
||||||
|
let changedValue = moveDelta / mainGestureViewHalfHeight
|
||||||
|
|
||||||
|
if panBeganPoint.x < mainGestureViewHalfWidth {
|
||||||
|
UIScreen.main.brightness = panBeganBrightness - changedValue
|
||||||
|
flashBrightnessOverlay()
|
||||||
|
} else if let view = volumeView.subviews.first as? UISlider {
|
||||||
|
view.value = panBeganVolumeValue - Float(changedValue)
|
||||||
|
flashVolumeOverlay()
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
hideSystemControlOverlay()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: setupOverlayHostingController
|
// MARK: setupOverlayHostingController
|
||||||
|
|
||||||
private func setupOverlayHostingController(viewModel: VideoPlayerViewModel) {
|
private func setupOverlayHostingController(viewModel: VideoPlayerViewModel) {
|
||||||
|
@ -560,6 +611,53 @@ extension VLCPlayerViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Show/Hide System Control
|
||||||
|
|
||||||
|
extension VLCPlayerViewController {
|
||||||
|
private func flashBrightnessOverlay() {
|
||||||
|
guard !displayingOverlay else { return }
|
||||||
|
|
||||||
|
let imageAttachment = NSTextAttachment()
|
||||||
|
imageAttachment.image = UIImage(systemName: "sun.max", withConfiguration: UIImage.SymbolConfiguration(pointSize: 48))?
|
||||||
|
.withTintColor(.white)
|
||||||
|
|
||||||
|
let attributedString = NSMutableAttributedString()
|
||||||
|
attributedString.append(.init(attachment: imageAttachment))
|
||||||
|
attributedString.append(.init(string: " \(String(format: "%.0f", UIScreen.main.brightness * 100))%"))
|
||||||
|
systemControlOverlayLabel.attributedText = attributedString
|
||||||
|
systemControlOverlayLabel.layer.removeAllAnimations()
|
||||||
|
|
||||||
|
UIView.animate(withDuration: 0.1) {
|
||||||
|
self.systemControlOverlayLabel.alpha = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func flashVolumeOverlay() {
|
||||||
|
guard !displayingOverlay,
|
||||||
|
let value = (volumeView.subviews.first as? UISlider)?.value else { return }
|
||||||
|
|
||||||
|
let imageAttachment = NSTextAttachment()
|
||||||
|
imageAttachment.image = UIImage(systemName: "speaker.wave.2", withConfiguration: UIImage.SymbolConfiguration(pointSize: 48))?
|
||||||
|
.withTintColor(.white)
|
||||||
|
|
||||||
|
let attributedString = NSMutableAttributedString()
|
||||||
|
attributedString.append(.init(attachment: imageAttachment))
|
||||||
|
attributedString.append(.init(string: " \(String(format: "%.0f", value * 100))%"))
|
||||||
|
systemControlOverlayLabel.attributedText = attributedString
|
||||||
|
systemControlOverlayLabel.layer.removeAllAnimations()
|
||||||
|
|
||||||
|
UIView.animate(withDuration: 0.1) {
|
||||||
|
self.systemControlOverlayLabel.alpha = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func hideSystemControlOverlay() {
|
||||||
|
UIView.animate(withDuration: 0.75) {
|
||||||
|
self.systemControlOverlayLabel.alpha = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Show/Hide Jump
|
// MARK: Show/Hide Jump
|
||||||
|
|
||||||
extension VLCPlayerViewController {
|
extension VLCPlayerViewController {
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue