mirror of
https://github.com/cranci1/Sora.git
synced 2026-04-21 00:22:12 +00:00
added close button
This commit is contained in:
parent
5ccbbf1c1b
commit
71d243dba5
5 changed files with 187 additions and 170 deletions
Binary file not shown.
|
|
@ -4,7 +4,7 @@
|
||||||
//
|
//
|
||||||
// Created by Pratik on 14/01/23.
|
// Created by Pratik on 14/01/23.
|
||||||
//
|
//
|
||||||
// Thanks to pratikg29 for this code inside his open source project "https://github.com/pratikg29/Custom-Slider-Control?ref=iosexample.com"
|
// Thanks to pratikg29 for this code inside his open source project "https://github.com/pratikg29/Custom-Slider-Control?ref=iosexample.com"
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@
|
||||||
//
|
//
|
||||||
// Created by Pratik on 08/01/23.
|
// Created by Pratik on 08/01/23.
|
||||||
//
|
//
|
||||||
// Thanks to pratikg29 for this code inside his open source project "https://github.com/pratikg29/Custom-Slider-Control?ref=iosexample.com"
|
// Thanks to pratikg29 for this code inside his open source project "https://github.com/pratikg29/Custom-Slider-Control?ref=iosexample.com"
|
||||||
|
// I did edit just a little bit the code for my liking
|
||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ struct CustomMediaPlayer: View {
|
||||||
@State private var duration: Double = 0.0
|
@State private var duration: Double = 0.0
|
||||||
@State private var showControls = false
|
@State private var showControls = false
|
||||||
@State private var inactivityTimer: Timer?
|
@State private var inactivityTimer: Timer?
|
||||||
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
|
||||||
init(urlString: String) {
|
init(urlString: String) {
|
||||||
guard let url = URL(string: urlString) else {
|
guard let url = URL(string: urlString) else {
|
||||||
|
|
@ -50,176 +51,194 @@ struct CustomMediaPlayer: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
ZStack {
|
||||||
ZStack {
|
VStack {
|
||||||
CustomVideoPlayer(player: player)
|
ZStack {
|
||||||
.onAppear {
|
CustomVideoPlayer(player: player)
|
||||||
player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: 600), queue: .main) { time in
|
.onAppear {
|
||||||
currentTime = time.seconds
|
player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: 600), queue: .main) { time in
|
||||||
if let itemDuration = player.currentItem?.duration.seconds, itemDuration.isFinite && !itemDuration.isNaN {
|
currentTime = time.seconds
|
||||||
duration = itemDuration
|
if let itemDuration = player.currentItem?.duration.seconds, itemDuration.isFinite && !itemDuration.isNaN {
|
||||||
|
duration = itemDuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startUpdatingCurrentTime()
|
||||||
|
}
|
||||||
|
.edgesIgnoringSafeArea(.all)
|
||||||
|
.overlay(
|
||||||
|
Group {
|
||||||
|
if showControls {
|
||||||
|
Color.black.opacity(0.5)
|
||||||
|
.edgesIgnoringSafeArea(.all)
|
||||||
|
HStack(spacing: 20) {
|
||||||
|
Button(action: {
|
||||||
|
currentTime = max(currentTime - 10, 0)
|
||||||
|
player.seek(to: CMTime(seconds: currentTime, preferredTimescale: 600))
|
||||||
|
}) {
|
||||||
|
Image(systemName: "gobackward.10")
|
||||||
|
}
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.font(.system(size: 25))
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.frame(width: 60, height: 60)
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
if isPlaying {
|
||||||
|
player.pause()
|
||||||
|
} else {
|
||||||
|
player.play()
|
||||||
|
}
|
||||||
|
isPlaying.toggle()
|
||||||
|
}) {
|
||||||
|
Image(systemName: isPlaying ? "pause.fill" : "play.fill")
|
||||||
|
}
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.font(.system(size: 45))
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.frame(width: 80, height: 80)
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
currentTime = min(currentTime + 10, duration)
|
||||||
|
player.seek(to: CMTime(seconds: currentTime, preferredTimescale: 600))
|
||||||
|
}) {
|
||||||
|
Image(systemName: "goforward.10")
|
||||||
|
}
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.font(.system(size: 25))
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.frame(width: 60, height: 60)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
alignment: .center
|
||||||
|
)
|
||||||
|
.onTapGesture {
|
||||||
|
showControls.toggle()
|
||||||
|
}
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
if showControls {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Menu {
|
||||||
|
Menu("Playback Speed") {
|
||||||
|
Button(action: {
|
||||||
|
player.rate = 0.25
|
||||||
|
if player.timeControlStatus != .playing {
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Label("0.25", systemImage: "tortoise")
|
||||||
|
}
|
||||||
|
Button(action: {
|
||||||
|
player.rate = 0.5
|
||||||
|
if player.timeControlStatus != .playing {
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Label("0.5", systemImage: "tortoise.fill")
|
||||||
|
}
|
||||||
|
Button(action: {
|
||||||
|
player.rate = 0.75
|
||||||
|
if player.timeControlStatus != .playing {
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Label("0.75", systemImage: "hare")
|
||||||
|
}
|
||||||
|
Button(action: {
|
||||||
|
player.rate = 1.0
|
||||||
|
if player.timeControlStatus != .playing {
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Label("1.0", systemImage: "hare.fill")
|
||||||
|
}
|
||||||
|
Button(action: {
|
||||||
|
player.rate = 1.25
|
||||||
|
if player.timeControlStatus != .playing {
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Label("1.25", systemImage: "speedometer")
|
||||||
|
}
|
||||||
|
Button(action: {
|
||||||
|
player.rate = 1.5
|
||||||
|
if player.timeControlStatus != .playing {
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Label("1.5", systemImage: "speedometer")
|
||||||
|
}
|
||||||
|
Button(action: {
|
||||||
|
player.rate = 1.75
|
||||||
|
if player.timeControlStatus != .playing {
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Label("1.75", systemImage: "speedometer")
|
||||||
|
}
|
||||||
|
Button(action: {
|
||||||
|
player.rate = 2.0
|
||||||
|
if player.timeControlStatus != .playing {
|
||||||
|
player.pause()
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Label("2.0", systemImage: "speedometer")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "ellipsis.circle")
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.font(.system(size: 15))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.trailing, 10)
|
||||||
|
|
||||||
|
MusicProgressSlider(
|
||||||
|
value: $currentTime,
|
||||||
|
inRange: 0...duration,
|
||||||
|
activeFillColor: .white,
|
||||||
|
fillColor: .white.opacity(0.5),
|
||||||
|
emptyColor: .white.opacity(0.3),
|
||||||
|
height: 28,
|
||||||
|
onEditingChanged: { editing in
|
||||||
|
if !editing {
|
||||||
|
player.seek(to: CMTime(seconds: currentTime, preferredTimescale: 600))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.frame(height: 45)
|
||||||
|
.padding(.bottom, 10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
startUpdatingCurrentTime()
|
startUpdatingCurrentTime()
|
||||||
}
|
}
|
||||||
.edgesIgnoringSafeArea(.all)
|
.onDisappear {
|
||||||
.overlay(
|
player.pause()
|
||||||
Group {
|
inactivityTimer?.invalidate()
|
||||||
if showControls {
|
|
||||||
Color.black.opacity(0.5)
|
|
||||||
.edgesIgnoringSafeArea(.all)
|
|
||||||
HStack(spacing: 20) {
|
|
||||||
Button(action: {
|
|
||||||
currentTime = max(currentTime - 10, 0)
|
|
||||||
player.seek(to: CMTime(seconds: currentTime, preferredTimescale: 600))
|
|
||||||
}) {
|
|
||||||
Image(systemName: "gobackward.10")
|
|
||||||
}
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.font(.system(size: 25))
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
.frame(width: 60, height: 60)
|
|
||||||
|
|
||||||
Button(action: {
|
|
||||||
if isPlaying {
|
|
||||||
player.pause()
|
|
||||||
} else {
|
|
||||||
player.play()
|
|
||||||
}
|
|
||||||
isPlaying.toggle()
|
|
||||||
}) {
|
|
||||||
Image(systemName: isPlaying ? "pause.fill" : "play.fill")
|
|
||||||
}
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.font(.system(size: 45))
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
.frame(width: 80, height: 80)
|
|
||||||
|
|
||||||
Button(action: {
|
|
||||||
currentTime = min(currentTime + 10, duration)
|
|
||||||
player.seek(to: CMTime(seconds: currentTime, preferredTimescale: 600))
|
|
||||||
}) {
|
|
||||||
Image(systemName: "goforward.10")
|
|
||||||
}
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.font(.system(size: 25))
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
.frame(width: 60, height: 60)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
alignment: .center
|
|
||||||
)
|
|
||||||
.onTapGesture {
|
|
||||||
showControls.toggle()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
VStack {
|
}
|
||||||
Spacer()
|
VStack {
|
||||||
if showControls {
|
if showControls {
|
||||||
VStack {
|
HStack {
|
||||||
Spacer()
|
Button(action: {
|
||||||
HStack {
|
presentationMode.wrappedValue.dismiss()
|
||||||
Spacer()
|
}) {
|
||||||
Menu {
|
Image(systemName: "xmark")
|
||||||
Menu("Playback Speed") {
|
.foregroundColor(.white)
|
||||||
Button(action: {
|
.font(.system(size: 20))
|
||||||
player.rate = 0.25
|
|
||||||
if player.timeControlStatus != .playing {
|
|
||||||
player.pause()
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Label("0.25", systemImage: "tortoise")
|
|
||||||
}
|
|
||||||
Button(action: {
|
|
||||||
player.rate = 0.5
|
|
||||||
if player.timeControlStatus != .playing {
|
|
||||||
player.pause()
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Label("0.5", systemImage: "tortoise.fill")
|
|
||||||
}
|
|
||||||
Button(action: {
|
|
||||||
player.rate = 0.75
|
|
||||||
if player.timeControlStatus != .playing {
|
|
||||||
player.pause()
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Label("0.75", systemImage: "hare")
|
|
||||||
}
|
|
||||||
Button(action: {
|
|
||||||
player.rate = 1.0
|
|
||||||
if player.timeControlStatus != .playing {
|
|
||||||
player.pause()
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Label("1.0", systemImage: "hare.fill")
|
|
||||||
}
|
|
||||||
Button(action: {
|
|
||||||
player.rate = 1.25
|
|
||||||
if player.timeControlStatus != .playing {
|
|
||||||
player.pause()
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Label("1.25", systemImage: "speedometer")
|
|
||||||
}
|
|
||||||
Button(action: {
|
|
||||||
player.rate = 1.5
|
|
||||||
if player.timeControlStatus != .playing {
|
|
||||||
player.pause()
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Label("1.5", systemImage: "speedometer")
|
|
||||||
}
|
|
||||||
Button(action: {
|
|
||||||
player.rate = 1.75
|
|
||||||
if player.timeControlStatus != .playing {
|
|
||||||
player.pause()
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Label("1.75", systemImage: "speedometer")
|
|
||||||
}
|
|
||||||
Button(action: {
|
|
||||||
player.rate = 2.0
|
|
||||||
if player.timeControlStatus != .playing {
|
|
||||||
player.pause()
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Label("2.0", systemImage: "speedometer")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "ellipsis.circle")
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.font(.system(size: 15))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.trailing, 10)
|
|
||||||
|
|
||||||
MusicProgressSlider(
|
|
||||||
value: $currentTime,
|
|
||||||
inRange: 0...duration,
|
|
||||||
activeFillColor: .white,
|
|
||||||
fillColor: .white.opacity(0.5),
|
|
||||||
emptyColor: .white.opacity(0.3),
|
|
||||||
height: 28,
|
|
||||||
onEditingChanged: { editing in
|
|
||||||
if !editing {
|
|
||||||
player.seek(to: CMTime(seconds: currentTime, preferredTimescale: 600))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.frame(height: 45)
|
|
||||||
.padding(.bottom, 10)
|
|
||||||
}
|
}
|
||||||
|
.padding()
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
}
|
Spacer()
|
||||||
.onAppear {
|
|
||||||
startUpdatingCurrentTime()
|
|
||||||
}
|
|
||||||
.onDisappear {
|
|
||||||
player.pause()
|
|
||||||
inactivityTimer?.invalidate()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -230,4 +249,4 @@ struct CustomMediaPlayer: View {
|
||||||
currentTime = player.currentTime().seconds
|
currentTime = player.currentTime().seconds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,7 @@ struct SettingsView: View {
|
||||||
Text("Minor Interface Settings")
|
Text("Minor Interface Settings")
|
||||||
}
|
}
|
||||||
NavigationLink(destination: SettingsPlayerView()) {
|
NavigationLink(destination: SettingsPlayerView()) {
|
||||||
HStack {
|
Text("Player")
|
||||||
Image(systemName: "play.fill")
|
|
||||||
Text("Player")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue