small delay before vertical scrubbing is possible

This avoids accidentally scrubbing. The screen now needs to be touched at least 250 ms before time scrubbing is possible.

should fix #393
This commit is contained in:
Toni Förster 2024-05-01 18:37:42 +02:00
parent d1cf45c6a1
commit 3da081b40c
No known key found for this signature in database
GPG Key ID: 292F3E5086C83FC7
2 changed files with 97 additions and 65 deletions

View File

@ -3,81 +3,109 @@ import SwiftUI
extension VideoPlayerView {
var playerDragGesture: some Gesture {
DragGesture(minimumDistance: 30, coordinateSpace: .global)
#if os(iOS)
let longPressGesture = LongPressGesture(minimumDuration: 0)
.updating($isLongPressing) { currentState, gestureState, _ in
gestureState = currentState
}
.onEnded { _ in
if startTouchTime == nil {
startTouchTime = Date()
}
}
let dragGesture = DragGesture(minimumDistance: 30, coordinateSpace: .global)
.updating($dragGestureOffset) { value, state, _ in
guard isVerticalDrag else { return }
var translation = value.translation
translation.height = max(0, translation.height)
state = translation
}
#endif
.updating($dragGestureState) { _, state, _ in
state = true
}
.onChanged { value in
guard player.presentingPlayer,
!controlsOverlayModel.presenting,
dragGestureState else { return }
if player.controls.presentingControls, !player.musicMode {
player.controls.presentingControls = false
}
if player.musicMode {
player.backend.stopControlsUpdates()
}
let verticalDrag = value.translation.height
let horizontalDrag = value.translation.width
#if os(iOS)
if viewDragOffset > 0, !isVerticalDrag {
isVerticalDrag = true
}
#endif
if !isVerticalDrag,
horizontalPlayerGestureEnabled,
abs(horizontalDrag) > seekGestureSensitivity,
!isHorizontalDrag,
player.activeBackend == .mpv || !avPlayerUsesSystemControls
{
isHorizontalDrag = true
player.seek.onSeekGestureStart()
viewDragOffset = 0
}
if horizontalPlayerGestureEnabled, isHorizontalDrag {
player.seek.updateCurrentTime {
let time = player.backend.playerItemDuration?.seconds ?? 0
if player.seek.gestureStart.isNil {
player.seek.gestureStart = time
}
let timeSeek = (time / player.playerSize.width) * horizontalDrag * seekGestureSpeed
player.seek.gestureSeek = timeSeek
}
return
}
guard verticalDrag > 0 else { return }
viewDragOffset = verticalDrag
if verticalDrag > 60,
player.playingFullScreen
{
player.exitFullScreen(showControls: false)
#if os(iOS)
if Constants.isIPhone {
Orientation.lockOrientation(.allButUpsideDown, andRotateTo: .portrait)
}
#endif
if abs(value.translation.width) < abs(value.translation.height) {
processDragGesture(value)
} else if getElapsedTouchTime() >= 0.25 {
processDragGesture(value)
}
}
.onEnded { _ in
onPlayerDragGestureEnded()
.onEnded { value in
if abs(value.translation.width) < abs(value.translation.height) {
onPlayerDragGestureEnded()
} else if getElapsedTouchTime() >= 0.25 {
onPlayerDragGestureEnded()
}
startTouchTime = nil
}
return longPressGesture.sequenced(before: dragGesture)
}
func getElapsedTouchTime() -> TimeInterval {
guard let startTouchTime = startTouchTime else {
return 0
}
return Date().timeIntervalSince(startTouchTime)
}
func processDragGesture(_ value: DragGesture.Value) {
guard player.presentingPlayer,
!controlsOverlayModel.presenting,
dragGestureState else { return }
if player.controls.presentingControls, !player.musicMode {
player.controls.presentingControls = false
}
if player.musicMode {
player.backend.stopControlsUpdates()
}
let verticalDrag = value.translation.height
let horizontalDrag = value.translation.width
#if os(iOS)
if viewDragOffset > 0, !isVerticalDrag {
isVerticalDrag = true
}
#endif
if !isVerticalDrag,
horizontalPlayerGestureEnabled,
abs(horizontalDrag) > seekGestureSensitivity,
!isHorizontalDrag,
player.activeBackend == .mpv || !avPlayerUsesSystemControls
{
isHorizontalDrag = true
player.seek.onSeekGestureStart()
viewDragOffset = 0
}
if horizontalPlayerGestureEnabled, isHorizontalDrag {
player.seek.updateCurrentTime {
let time = player.backend.playerItemDuration?.seconds ?? 0
if player.seek.gestureStart.isNil {
player.seek.gestureStart = time
}
let timeSeek = (time / player.playerSize.width) * horizontalDrag * seekGestureSpeed
player.seek.gestureSeek = timeSeek
}
return
}
guard verticalDrag > 0 else { return }
viewDragOffset = verticalDrag
if verticalDrag > 60, player.playingFullScreen {
player.exitFullScreen(showControls: false)
#if os(iOS)
if Constants.isIPhone {
Orientation.lockOrientation(.allButUpsideDown, andRotateTo: .portrait)
}
#endif
}
}
func onPlayerDragGestureEnded() {

View File

@ -47,9 +47,13 @@ struct VideoPlayerView: View {
#if !os(tvOS)
@GestureState var dragGestureState = false
@GestureState var dragGestureOffset = CGSize.zero
@State var isHorizontalDrag = false // swiftlint:disable:this swiftui_state_private
@State var isVerticalDrag = false // swiftlint:disable:this swiftui_state_private
@State var viewDragOffset = Self.hiddenOffset // swiftlint:disable:this swiftui_state_private
@GestureState var isLongPressing = false
// swiftlint:disable swiftui_state_private
@State var isHorizontalDrag = false
@State var isVerticalDrag = false
@State var viewDragOffset = Self.hiddenOffset
@State var startTouchTime: Date? = nil
// swiftlint:enable swiftui_state_private
#endif
@ObservedObject var player = PlayerModel.shared // swiftlint:disable:this swiftui_state_private