Improve seek gesture

This commit is contained in:
Arkadiusz Fal
2022-08-29 13:55:23 +02:00
parent d5f8ad4eec
commit e444dc3c79
14 changed files with 238 additions and 158 deletions

View File

@@ -7,10 +7,7 @@ struct Seek: View {
#endif
@EnvironmentObject<PlayerControlsModel> private var controls
@EnvironmentObject<PlayerTimeModel> private var model
@State private var dismissTimer: Timer?
@State private var isSeeking = false
@EnvironmentObject<SeekModel> private var model
private var updateThrottle = Throttle(interval: 2)
@@ -20,12 +17,12 @@ struct Seek: View {
var body: some View {
Button(action: model.restoreTime) {
VStack(spacing: playerControlsLayout.osdSpacing) {
ProgressBar(value: progress)
ProgressBar(value: model.progress)
.frame(maxHeight: playerControlsLayout.osdProgressBarHeight)
timeline
if isSeeking {
if model.isSeeking {
Divider()
gestureSeekTime
.foregroundColor(.secondary)
@@ -84,38 +81,10 @@ struct Seek: View {
.buttonStyle(.plain)
#endif
.opacity(visible || YatteeApp.isForPreviews ? 1 : 0)
.onChange(of: model.lastSeekTime) { _ in
isSeeking = false
dismissTimer?.invalidate()
dismissTimer = Delay.by(3) {
withAnimation(.easeIn(duration: 0.1)) { model.seekOSDDismissed = true }
}
if model.seekOSDDismissed {
withAnimation(.easeIn(duration: 0.1)) { self.model.seekOSDDismissed = false }
}
}
.onChange(of: model.gestureSeek) { newValue in
let newIsSeekingValue = isSeeking || model.gestureSeek != 0
if !isSeeking, newIsSeekingValue {
model.onSeekGestureStart()
}
isSeeking = newIsSeekingValue
guard newValue != 0 else { return }
updateThrottle.execute {
model.player.backend.getTimeUpdates()
model.player.backend.updateControls()
}
dismissTimer?.invalidate()
if model.seekOSDDismissed {
withAnimation(.easeIn(duration: 0.1)) { self.model.seekOSDDismissed = false }
}
}
}
var timeline: some View {
let text = model.gestureSeek != 0 && model.lastSeekTime.isNil ?
let text = model.isSeeking ?
"\(model.gestureSeekDestinationPlaybackTime)/\(model.durationPlaybackTime)" :
"\(model.lastSeekPlaybackTime)/\(model.durationPlaybackTime)"
@@ -141,21 +110,10 @@ struct Seek: View {
}
var visible: Bool {
guard !(model.lastSeekTime.isNil && !isSeeking) else { return false }
guard !(model.lastSeekTime.isNil && !model.isSeeking) else { return false }
if let type = model.lastSeekType, !type.presentable { return false }
return !controls.presentingControls && !controls.presentingOverlays && !model.seekOSDDismissed
}
var progress: Double {
if isSeeking {
return model.gestureSeekDestinationTime / model.duration.seconds
}
guard model.duration.seconds.isFinite, model.duration.seconds > 0 else { return 0 }
guard let seekTime = model.lastSeekTime else { return model.currentTime.seconds / model.duration.seconds }
return seekTime.seconds / model.duration.seconds
return !controls.presentingControls && !controls.presentingOverlays && model.presentingOSD
}
var projectedChapter: Chapter? {

View File

@@ -51,7 +51,7 @@ struct PlayerControls: View {
#if os(tvOS)
.offset(x: 10, y: 10)
.focused($focusedField, equals: .seekOSD)
.onChange(of: player.playerTime.lastSeekTime) { _ in
.onChange(of: player.seek.lastSeekTime) { _ in
if !model.presentingControls {
focusedField = .seekOSD
}

View File

@@ -1,4 +1,3 @@
import SwiftUI
struct ProgressBar: View {
@@ -11,7 +10,7 @@ struct ProgressBar: View {
.opacity(0.3)
.foregroundColor(Color.secondary)
Rectangle().frame(width: min(CGFloat(self.value) * geometry.size.width, geometry.size.width), height: geometry.size.height)
Rectangle().frame(width: min(Double(self.value) * geometry.size.width, geometry.size.width), height: geometry.size.height)
.foregroundColor(Color.accentColor)
.animation(.linear)
}.cornerRadius(45.0)

View File

@@ -72,7 +72,7 @@ struct TVControls: UIViewRepresentable {
}
@objc func handleTap(sender _: UITapGestureRecognizer) {
if !model.presentingControls, model.player.playerTime.seekOSDDismissed {
if !model.presentingControls {
model.show()
}
}

View File

@@ -38,14 +38,19 @@ extension VideoPlayerView {
if !isVerticalDrag, abs(horizontalDrag) > 15, !isHorizontalDrag {
isHorizontalDrag = true
player.playerTime.resetSeek()
player.seek.onSeekGestureStart()
viewDragOffset = 0
}
if horizontalPlayerGestureEnabled, isHorizontalDrag {
player.playerTime.onSeekGestureStart {
let timeSeek = (player.playerTime.duration.seconds / player.playerSize.width) * horizontalDrag * seekGestureSpeed
player.playerTime.gestureSeek = timeSeek
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
}
@@ -72,7 +77,7 @@ extension VideoPlayerView {
private func onPlayerDragGestureEnded() {
if horizontalPlayerGestureEnabled, isHorizontalDrag {
isHorizontalDrag = false
player.playerTime.onSeekGestureEnd()
player.seek.onSeekGestureEnd()
}
isVerticalDrag = false