akborana4 commited on
Commit
99ece78
·
verified ·
1 Parent(s): adc4224

Create Player.jsx

Browse files
Files changed (1) hide show
  1. client/src/Player.jsx +60 -0
client/src/Player.jsx ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useEffect, useRef } from 'react';
2
+
3
+ export default function Player({ socket, roomId, state, isHost }) {
4
+ const audioRef = useRef(null);
5
+
6
+ // Compute desired current time from {anchor, anchorAt, isPlaying}
7
+ const logicalTime = () => {
8
+ if (!state) return 0;
9
+ const { anchor, anchorAt, isPlaying } = state;
10
+ if (!isPlaying) return anchor || 0;
11
+ const elapsed = (Date.now() - (anchorAt || 0)) / 1000;
12
+ return Math.max(0, (anchor || 0) + elapsed);
13
+ };
14
+
15
+ useEffect(() => {
16
+ const el = audioRef.current;
17
+ if (!el || !state?.track?.url) return;
18
+
19
+ // On track change load new source
20
+ el.src = state.track.url;
21
+ el.load();
22
+ // Apply initial position
23
+ const target = logicalTime();
24
+ el.currentTime = isFinite(target) ? target : 0;
25
+ if (state.isPlaying) el.play().catch(() => {});
26
+ else el.pause();
27
+ }, [state?.track?.url]); // run when track changes
28
+
29
+ // Respond to play/pause/seek from server
30
+ useEffect(() => {
31
+ const el = audioRef.current;
32
+ if (!el) return;
33
+ const target = logicalTime();
34
+ // Small drift correction
35
+ const drift = target - el.currentTime;
36
+ if (Math.abs(drift) > 0.3) {
37
+ el.currentTime = Math.max(0, target);
38
+ }
39
+ if (state.isPlaying && el.paused) el.play().catch(() => {});
40
+ if (!state.isPlaying && !el.paused) el.pause();
41
+ }, [state.isPlaying, state.anchor, state.anchorAt]);
42
+
43
+ // Optionally, report local ended event to host
44
+ useEffect(() => {
45
+ const el = audioRef.current;
46
+ if (!el) return;
47
+ const onEnded = () => {
48
+ // For future: queue/next
49
+ };
50
+ el.addEventListener('ended', onEnded);
51
+ return () => el.removeEventListener('ended', onEnded);
52
+ }, []);
53
+
54
+ return (
55
+ <div style={{ marginTop: 16 }}>
56
+ <div style={{ marginBottom: 8 }}>{state?.track?.title || 'No track selected'}</div>
57
+ <audio ref={audioRef} controls style={{ width: '100%' }} crossorigin="anonymous" />
58
+ </div>
59
+ );
60
+ }