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") }
|
||||
/// 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
|
||||
internal static var tags: String { return L10n.tr("Localizable", "tags") }
|
||||
/// Too Many Redirects
|
||||
|
|
|
@ -46,6 +46,8 @@ extension Defaults.Keys {
|
|||
// Video player / overlay settings
|
||||
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 systemControlGesturesEnabled = Key<Bool>("systemControlGesturesEnabled", default: true,
|
||||
suite: SwiftfinStore.Defaults.generalSuite)
|
||||
static let videoPlayerJumpForward = Key<VideoPlayerJumpLength>("videoPlayerJumpForward", default: .fifteen,
|
||||
suite: SwiftfinStore.Defaults.generalSuite)
|
||||
static let videoPlayerJumpBackward = Key<VideoPlayerJumpLength>("videoPlayerJumpBackward", default: .fifteen,
|
||||
|
|
|
@ -115,6 +115,7 @@ final class VideoPlayerViewModel: ViewModel {
|
|||
let chapters: [ChapterInfo]
|
||||
let overlayType: OverlayType
|
||||
let jumpGesturesEnabled: Bool
|
||||
let systemControlGesturesEnabled: Bool
|
||||
let resumeOffset: Bool
|
||||
let streamType: ServerStreamType
|
||||
let container: String
|
||||
|
@ -241,6 +242,7 @@ final class VideoPlayerViewModel: ViewModel {
|
|||
self.jumpBackwardLength = Defaults[.videoPlayerJumpBackward]
|
||||
self.jumpForwardLength = Defaults[.videoPlayerJumpForward]
|
||||
self.jumpGesturesEnabled = Defaults[.jumpGesturesEnabled]
|
||||
self.systemControlGesturesEnabled = Defaults[.systemControlGesturesEnabled]
|
||||
self.shouldShowJumpButtonsInOverlayMenu = Defaults[.shouldShowJumpButtonsInOverlayMenu]
|
||||
|
||||
self.resumeOffset = Defaults[.resumeOffset]
|
||||
|
|
|
@ -38,31 +38,6 @@ struct LibraryListView: View {
|
|||
self.mainCoordinator.root(\.liveTV)
|
||||
}
|
||||
label: {
|
||||
ZStack {
|
||||
HStack {
|
||||
Spacer()
|
||||
VStack {
|
||||
Text(library.name ?? "")
|
||||
.foregroundColor(.white)
|
||||
.font(.title2)
|
||||
.fontWeight(.semibold)
|
||||
}
|
||||
Spacer()
|
||||
}.padding(32)
|
||||
}
|
||||
.frame(minWidth: 100, maxWidth: .infinity)
|
||||
.frame(height: 100)
|
||||
}
|
||||
.cornerRadius(10)
|
||||
.shadow(radius: 5)
|
||||
.padding(.bottom, 5)
|
||||
}
|
||||
} else {
|
||||
Button {
|
||||
self.libraryListRouter.route(to: \.library,
|
||||
(viewModel: LibraryViewModel(parentID: library.id), title: library.name ?? ""))
|
||||
}
|
||||
label: {
|
||||
ZStack {
|
||||
HStack {
|
||||
Spacer()
|
||||
|
@ -81,6 +56,31 @@ struct LibraryListView: View {
|
|||
.cornerRadius(10)
|
||||
.shadow(radius: 5)
|
||||
.padding(.bottom, 5)
|
||||
}
|
||||
} else {
|
||||
Button {
|
||||
self.libraryListRouter.route(to: \.library,
|
||||
(viewModel: LibraryViewModel(parentID: library.id), title: library.name ?? ""))
|
||||
}
|
||||
label: {
|
||||
ZStack {
|
||||
HStack {
|
||||
Spacer()
|
||||
VStack {
|
||||
Text(library.name ?? "")
|
||||
.foregroundColor(.white)
|
||||
.font(.title2)
|
||||
.fontWeight(.semibold)
|
||||
}
|
||||
Spacer()
|
||||
}.padding(32)
|
||||
}
|
||||
.frame(minWidth: 100, maxWidth: .infinity)
|
||||
.frame(height: 100)
|
||||
}
|
||||
.cornerRadius(10)
|
||||
.shadow(radius: 5)
|
||||
.padding(.bottom, 5)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -38,6 +38,8 @@ struct SettingsView: View {
|
|||
var jumpBackwardLength
|
||||
@Default(.jumpGesturesEnabled)
|
||||
var jumpGesturesEnabled
|
||||
@Default(.systemControlGesturesEnabled)
|
||||
var systemControlGesturesEnabled
|
||||
@Default(.resumeOffset)
|
||||
var resumeOffset
|
||||
@Default(.subtitleSize)
|
||||
|
@ -107,6 +109,8 @@ struct SettingsView: View {
|
|||
|
||||
Toggle(L10n.jumpGesturesEnabled, isOn: $jumpGesturesEnabled)
|
||||
|
||||
Toggle(L10n.systemControlGesturesEnabled, isOn: $systemControlGesturesEnabled)
|
||||
|
||||
Toggle(L10n.resume5SecondOffset, isOn: $resumeOffset)
|
||||
|
||||
Button {
|
||||
|
|
|
@ -42,12 +42,18 @@ class VLCPlayerViewController: UIViewController {
|
|||
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 mainGestureView = makeMainGestureView()
|
||||
private var currentOverlayHostingController: UIHostingController<VLCPlayerOverlayView>?
|
||||
private var currentChapterOverlayHostingController: UIHostingController<VLCPlayerChapterOverlayView>?
|
||||
private var systemControlOverlayLabel = UILabel()
|
||||
private var currentJumpBackwardOverlayView: UIImageView?
|
||||
private var currentJumpForwardOverlayView: UIImageView?
|
||||
private var volumeView = MPVolumeView()
|
||||
|
||||
override var keyCommands: [UIKeyCommand]? {
|
||||
var commands = [
|
||||
|
@ -95,6 +101,12 @@ class VLCPlayerViewController: UIViewController {
|
|||
private func setupSubviews() {
|
||||
view.addSubview(videoContentView)
|
||||
view.addSubview(mainGestureView)
|
||||
|
||||
// Setup BrightnessOverlayView
|
||||
systemControlOverlayLabel.alpha = 0
|
||||
systemControlOverlayLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
systemControlOverlayLabel.font = .systemFont(ofSize: 48)
|
||||
view.addSubview(systemControlOverlayLabel)
|
||||
}
|
||||
|
||||
private func setupConstraints() {
|
||||
|
@ -110,6 +122,10 @@ class VLCPlayerViewController: UIViewController {
|
|||
mainGestureView.leftAnchor.constraint(equalTo: videoContentView.leftAnchor),
|
||||
mainGestureView.rightAnchor.constraint(equalTo: videoContentView.rightAnchor),
|
||||
])
|
||||
NSLayoutConstraint.activate([
|
||||
systemControlOverlayLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
|
||||
systemControlOverlayLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
|
||||
])
|
||||
}
|
||||
|
||||
// MARK: viewWillDisappear
|
||||
|
@ -202,6 +218,8 @@ class VLCPlayerViewController: UIViewController {
|
|||
|
||||
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(didPinch(_:)))
|
||||
|
||||
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(didPan(_:)))
|
||||
|
||||
view.addGestureRecognizer(singleTapGesture)
|
||||
view.addGestureRecognizer(pinchGesture)
|
||||
|
||||
|
@ -210,6 +228,10 @@ class VLCPlayerViewController: UIViewController {
|
|||
view.addGestureRecognizer(leftSwipeGesture)
|
||||
}
|
||||
|
||||
if viewModel.systemControlGesturesEnabled {
|
||||
view.addGestureRecognizer(panGesture)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
extension VLCPlayerViewController {
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue