1
0
mirror of https://github.com/yattee/yattee.git synced 2024-12-13 05:40:32 +05:30

Minor player controls improvements (fix #94)

This commit is contained in:
Arkadiusz Fal 2022-05-28 00:59:35 +02:00
parent 45d591537c
commit e3cf77e928
5 changed files with 109 additions and 59 deletions

View File

@ -241,7 +241,11 @@ final class MPVBackend: PlayerBackend {
client?.setDoubleAsync("speed", Double(rate))
}
func closeItem() {}
func closeItem() {
handleEOF = false
client?.pause()
client?.stop()
}
func enterFullScreen() {}

View File

@ -371,7 +371,11 @@ final class PlayerModel: ObservableObject {
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
self?.upgradeToStream(stream, force: true)
guard let self = self else {
return
}
self.upgradeToStream(stream, force: true)
self.setNeedsDrawing(self.presentingPlayer)
}
}
@ -448,6 +452,10 @@ final class PlayerModel: ObservableObject {
logger.info("exiting fullscreen")
if controls.playingFullscreen {
toggleFullscreen(true)
}
backend.exitFullScreen()
}
#endif

View File

@ -53,18 +53,21 @@ struct PlayerControls: View {
Spacer()
timeline
.offset(y: 10)
.zIndex(1)
Group {
timeline
.offset(y: 10)
.zIndex(1)
bottomBar
bottomBar
#if os(macOS)
.background(VisualEffectBlur(material: .hudWindow))
#elseif os(iOS)
.background(VisualEffectBlur(blurStyle: .systemThinMaterial))
#endif
.mask(RoundedRectangle(cornerRadius: 3))
#if os(macOS)
.background(VisualEffectBlur(material: .hudWindow))
#elseif os(iOS)
.background(VisualEffectBlur(blurStyle: .systemThinMaterial))
#endif
.mask(RoundedRectangle(cornerRadius: 3))
}
.padding(.horizontal, 16)
}
}
.opacity(model.presentingControls ? 1 : 0)
@ -104,9 +107,6 @@ struct PlayerControls: View {
var statusBar: some View {
HStack(spacing: 4) {
#if os(iOS)
hidePlayerButton
#endif
Text(playbackStatus)
Text("")
@ -129,11 +129,10 @@ struct PlayerControls: View {
}
private var hidePlayerButton: some View {
Button {
button("Hide", systemImage: "chevron.down") {
player.hide()
} label: {
Image(systemName: "chevron.down.circle.fill")
}
#if !os(tvOS)
.keyboardShortcut(.cancelAction)
#endif
@ -170,14 +169,18 @@ struct PlayerControls: View {
}
var buttonsBar: some View {
HStack {
HStack(spacing: 20) {
#if !os(tvOS)
hidePlayerButton
fullscreenButton
#if os(iOS)
pipButton
#endif
rateButton
closeVideoButton
Spacer()
#endif
// button("Music Mode", systemImage: "music.note")
@ -225,6 +228,19 @@ struct PlayerControls: View {
#endif
}
private var closeVideoButton: some View {
button("Close", systemImage: "xmark") {
player.pause()
player.hide()
player.closePiP()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
player.closeCurrentItem()
}
}
}
var ratePicker: some View {
Picker("Rate", selection: rateBinding) {
ForEach(PlayerModel.availableRates, id: \.self) { rate in
@ -244,6 +260,8 @@ struct PlayerControls: View {
player.avPlayerBackend.switchToMPVOnPipClose = true
}
player.exitFullScreen()
if player.activeBackend != PlayerBackendType.appleAVPlayer {
player.saveTime {
player.changeActiveBackend(from: .mpv, to: .appleAVPlayer)
@ -261,7 +279,7 @@ struct PlayerControls: View {
var mediumButtonsBar: some View {
HStack {
#if !os(tvOS)
button("Seek Backward", systemImage: "gobackward.10", size: 50, cornerRadius: 10) {
button("Seek Backward", systemImage: "gobackward.10", size: 30, cornerRadius: 5) {
player.backend.seek(relative: .secondsInDefaultTimescale(-10))
}
@ -279,8 +297,7 @@ struct PlayerControls: View {
button(
model.isPlaying ? "Pause" : "Play",
systemImage: model.isPlaying ? "pause.fill" : "play.fill",
size: 50,
cornerRadius: 10
size: 30, cornerRadius: 5
) {
player.backend.togglePlay()
}
@ -295,7 +312,7 @@ struct PlayerControls: View {
Spacer()
#if !os(tvOS)
button("Seek Forward", systemImage: "goforward.10", size: 50, cornerRadius: 10) {
button("Seek Forward", systemImage: "goforward.10", size: 30, cornerRadius: 5) {
player.backend.seek(relative: .secondsInDefaultTimescale(10))
}
#if os(tvOS)
@ -306,7 +323,7 @@ struct PlayerControls: View {
#endif
#endif
}
.font(.system(size: 30))
.font(.system(size: 20))
.padding(.horizontal, 4)
}
@ -361,6 +378,25 @@ struct PlayerControls: View {
struct PlayerControls_Previews: PreviewProvider {
static var previews: some View {
PlayerControls(player: PlayerModel())
let model = PlayerControlsModel()
model.presentingControls = true
model.currentTime = .secondsInDefaultTimescale(0)
model.duration = .secondsInDefaultTimescale(120)
let view = ZStack {
Color.red
PlayerControls(player: PlayerModel())
.injectFixtureEnvironmentObjects()
.environmentObject(model)
}
return Group {
if #available(iOS 15.0, *) {
view.previewInterfaceOrientation(.landscapeLeft)
} else {
view
}
}
}
}

View File

@ -10,7 +10,7 @@ struct TimelineView: View {
@State private var draggedFrom: Double = 0
private var start: Double = 0.0
private var height = 10.0
private var height = 8.0
var cornerRadius: Double
var thumbTooltipWidth: Double = 100
@ -26,26 +26,26 @@ struct TimelineView: View {
var body: some View {
ZStack(alignment: .leading) {
RoundedRectangle(cornerRadius: cornerRadius)
.foregroundColor(.blue)
.frame(maxHeight: height)
Group {
RoundedRectangle(cornerRadius: cornerRadius)
.foregroundColor(.blue)
.frame(maxHeight: height)
RoundedRectangle(cornerRadius: cornerRadius)
.fill(
Color.green
)
.frame(maxHeight: height)
.frame(width: current * oneUnitWidth)
RoundedRectangle(cornerRadius: cornerRadius)
.fill(Color.green)
.frame(maxHeight: height)
.frame(width: current * oneUnitWidth)
segmentsLayers
segmentsLayers
}
.mask(RoundedRectangle(cornerRadius: 3))
Circle()
.strokeBorder(.gray, lineWidth: 1)
.background(Circle().fill(dragging ? .gray : .white))
.offset(x: thumbOffset)
.foregroundColor(.red.opacity(0.6))
.frame(maxHeight: height * 2)
.frame(maxHeight: height * 4)
#if !os(tvOS)
.gesture(
@ -114,7 +114,7 @@ struct TimelineView: View {
var projectedValue: Double {
let change = (dragOffset / size.width) * units
let projected = draggedFrom + change
return projected.isFinite ? projected : start
return projected.isFinite ? (duration - projected < (0.03 * duration) ? duration : projected) : start
}
var thumbOffset: Double {
@ -192,6 +192,7 @@ struct TimelineView_Previews: PreviewProvider {
TimelineView(duration: .constant(100), current: .constant(90))
TimelineView(duration: .constant(100), current: .constant(100))
}
.environmentObject(PlayerModel())
.padding()
}
}

View File

@ -138,17 +138,7 @@ struct VideoPlayerView: View {
hoveringPlayer = hovering
hovering ? playerControls.show() : playerControls.hide()
}
#if os(iOS)
.onSwipeGesture(
up: {
withAnimation {
fullScreenDetails = true
}
},
down: { player.hide() }
)
#elseif os(macOS)
#if os(macOS)
.onAppear(perform: {
NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) {
if hoveringPlayer {
@ -269,20 +259,31 @@ struct VideoPlayerView: View {
}
func playerPlaceholder(geometry: GeometryProxy) -> some View {
HStack {
Spacer()
VStack {
ZStack(alignment: .topLeading) {
HStack {
Spacer()
VStack(spacing: 10) {
#if !os(tvOS)
Image(systemName: "ticket")
.font(.system(size: 120))
#endif
VStack {
Spacer()
VStack(spacing: 10) {
#if !os(tvOS)
Image(systemName: "ticket")
.font(.system(size: 120))
#endif
}
Spacer()
}
.foregroundColor(.gray)
Spacer()
}
Button {
player.hide()
} label: {
Image(systemName: "xmark")
.font(.system(size: 40))
}
.padding(10)
.foregroundColor(.gray)
Spacer()
}
.contentShape(Rectangle())
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: geometry.size.width / Self.defaultAspectRatio)