Skip to content

Commit

Permalink
small delay before vertical scrubbing is possible
Browse files Browse the repository at this point in the history
This avoids accidentally scrubbing. The screen now needs to be touched at least 250 ms before time scrubbing is possible.

should fix yattee#393
  • Loading branch information
stonerl committed May 1, 2024
1 parent d1cf45c commit 3da081b
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 61 deletions.
144 changes: 86 additions & 58 deletions Shared/Player/PlayerDragGesture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 abs(value.translation.width) < abs(value.translation.height) {
processDragGesture(value)
} else if getElapsedTouchTime() >= 0.25 {
processDragGesture(value)
}

if player.musicMode {
player.backend.stopControlsUpdates()
}
.onEnded { value in
if abs(value.translation.width) < abs(value.translation.height) {
onPlayerDragGestureEnded()
} else if getElapsedTouchTime() >= 0.25 {
onPlayerDragGestureEnded()
}

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
}
startTouchTime = nil
}
return longPressGesture.sequenced(before: dragGesture)
}

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
}
func getElapsedTouchTime() -> TimeInterval {
guard let startTouchTime = startTouchTime else {
return 0
}
return Date().timeIntervalSince(startTouchTime)
}

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 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
}
.onEnded { _ in
onPlayerDragGestureEnded()
#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() {
Expand Down
10 changes: 7 additions & 3 deletions Shared/Player/VideoPlayerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 3da081b

Please sign in to comment.