Skip to content

Commit 6400c25

Browse files
committed
Fixed video player
1 parent 3ebf141 commit 6400c25

File tree

1 file changed

+9
-137
lines changed

1 file changed

+9
-137
lines changed

MacImageManager/MacImageManager/Views/PaneVideoViewer.swift

Lines changed: 9 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -12,85 +12,15 @@ struct PaneVideoViewer: View {
1212
let videoUrl: URL?
1313

1414
@State private var player: AVPlayer?
15-
@State private var isPlaying: Bool = false
16-
@State private var currentTime: Double = 0
17-
@State private var duration: Double = 0
18-
@State private var volume: Float = 1.0
19-
@State private var playbackRate: Float = 1.0
20-
21-
// Time observer
22-
@State private var timeObserver: Any?
2315

2416
var body: some View {
2517
Group {
26-
if let videoUrl = videoUrl {
27-
VStack {
28-
// Video Player
29-
ScrollView([.horizontal, .vertical]) {
30-
VideoPlayer(player: player)
31-
.containerRelativeFrame([.horizontal, .vertical])
32-
.background(Color.black)
33-
}
34-
35-
// Custom Controls
36-
VStack {
37-
// Time Slider and Labels
38-
HStack {
39-
Text(formatTime(currentTime))
40-
.font(.caption)
41-
.monospacedDigit()
42-
43-
Slider(value: Binding(
44-
get: { currentTime },
45-
set: { seek(to: $0) }
46-
), in: 0...duration)
47-
48-
Text(formatTime(duration))
49-
.font(.caption)
50-
.monospacedDigit()
51-
}
52-
53-
HStack {
54-
// Play/Pause
55-
Button(action: togglePlayPause) {
56-
Image(systemName: isPlaying ? "pause.circle" : "play.circle")
57-
.font(.title)
58-
}
59-
60-
// Rewind 10s
61-
Button(action: rewindTenSeconds) {
62-
Image(systemName: "gobackward.10")
63-
.font(.title)
64-
}
65-
66-
// Forward 10s
67-
Button(action: forwardTenSeconds) {
68-
Image(systemName: "goforward.10")
69-
.font(.title)
70-
}
71-
72-
// Volume
73-
HStack {
74-
Image(systemName: "speaker.wave.2")
75-
Slider(value: $volume, in: 0...1) {
76-
Text("Volume")
77-
}
78-
.frame(width: 100)
79-
}
80-
81-
// Playback Speed
82-
Menu {
83-
Button("0.5x") { setPlaybackRate(0.5) }
84-
Button("1.0x") { setPlaybackRate(1.0) }
85-
Button("1.5x") { setPlaybackRate(1.5) }
86-
Button("2.0x") { setPlaybackRate(2.0) }
87-
} label: {
88-
Text("\(String(format: "%.1fx", playbackRate))")
89-
}
90-
}
91-
}
92-
.padding()
93-
}
18+
if videoUrl != nil {
19+
// Video Player with built-in controls
20+
VideoPlayer(player: player)
21+
.background(Color.black)
22+
.clipShape(RoundedRectangle(cornerRadius: 8))
23+
.padding(16)
9424
} else {
9525
// Empty State
9626
VStack {
@@ -105,12 +35,12 @@ struct PaneVideoViewer: View {
10535
.background(Color(NSColor.controlBackgroundColor))
10636
}
10737
}
38+
.frame(maxWidth: .infinity, maxHeight: .infinity)
39+
//.background(Color(NSColor.windowBackgroundColor))
40+
.background(Color(NSColor.black))
10841
.onChange(of: videoUrl) { oldValue, newValue in
10942
loadVideo(from: newValue)
11043
}
111-
.onChange(of: volume) { oldValue, newValue in
112-
player?.volume = volume
113-
}
11444
.onAppear {
11545
loadVideo(from: videoUrl)
11646
}
@@ -127,73 +57,15 @@ struct PaneVideoViewer: View {
12757
let playerItem = AVPlayerItem(url: url)
12858
let newPlayer = AVPlayer(playerItem: playerItem)
12959

130-
// Set initial volume
131-
newPlayer.volume = volume
132-
133-
// Observe video duration
134-
let durationObserver = playerItem.observe(\.duration) { item, _ in
135-
duration = item.duration.seconds
136-
}
137-
138-
// Add time observer
139-
let interval = CMTime(seconds: 0.5, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
140-
timeObserver = newPlayer.addPeriodicTimeObserver(forInterval: interval, queue: .main) { time in
141-
currentTime = time.seconds
142-
}
143-
14460
self.player = newPlayer
14561
}
14662

14763
private func cleanup() {
148-
if let observer = timeObserver {
149-
player?.removeTimeObserver(observer)
150-
}
15164
player?.pause()
15265
player = nil
153-
isPlaying = false
154-
currentTime = 0
155-
duration = 0
156-
}
157-
158-
private func togglePlayPause() {
159-
isPlaying.toggle()
160-
if isPlaying {
161-
player?.play()
162-
} else {
163-
player?.pause()
164-
}
165-
}
166-
167-
private func seek(to time: Double) {
168-
let newTime = CMTime(seconds: time, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
169-
player?.seek(to: newTime)
17066
}
17167

172-
private func rewindTenSeconds() {
173-
seek(to: max(currentTime - 10, 0))
174-
}
17568

176-
private func forwardTenSeconds() {
177-
seek(to: min(currentTime + 10, duration))
178-
}
179-
180-
private func setPlaybackRate(_ rate: Float) {
181-
playbackRate = rate
182-
player?.rate = rate
183-
}
184-
185-
private func formatTime(_ seconds: Double) -> String {
186-
let time = Int(seconds)
187-
let hours = time / 3600
188-
let minutes = (time % 3600) / 60
189-
let seconds = time % 60
190-
191-
if hours > 0 {
192-
return String(format: "%d:%02d:%02d", hours, minutes, seconds)
193-
} else {
194-
return String(format: "%02d:%02d", minutes, seconds)
195-
}
196-
}
19769
}
19870

19971
#Preview("No Selection") {

0 commit comments

Comments
 (0)