apm-react-audio-player 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -27,15 +27,15 @@ function _iterableToArrayLimit(r, l) {
27
27
  i,
28
28
  u,
29
29
  a = [],
30
- f = !0,
31
- o = !1;
30
+ f = true,
31
+ o = false;
32
32
  try {
33
33
  if (i = (t = t.call(r)).next, 0 === l) {
34
34
  if (Object(t) !== t) return;
35
35
  f = !1;
36
36
  } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
37
37
  } catch (r) {
38
- o = !0, n = r;
38
+ o = true, n = r;
39
39
  } finally {
40
40
  try {
41
41
  if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
@@ -91,9 +91,13 @@ var useAudioPlayer = function useAudioPlayer(audioRef, progressBarRef, volumeCtr
91
91
  }
92
92
  }, [currentTime]);
93
93
  React.useEffect(function () {
94
- // Cancel RAF loop if duration changes to Infinity (live stream metadata loaded)
95
- if (duration === Infinity && animationRef.current) {
94
+ if (duration === Infinity) {
95
+ // Cancel RAF loop for live streams
96
+ if (animationRef.current) window.cancelAnimationFrame(animationRef.current);
97
+ } else if (duration && !isNaN(duration) && progressBarRef.current && audioRef.current && !audioRef.current.paused) {
98
+ // play() was called before metadata loaded — progressBarRef is now mounted, start loop
96
99
  window.cancelAnimationFrame(animationRef.current);
100
+ animationRef.current = window.requestAnimationFrame(_whilePlaying);
97
101
  }
98
102
  }, [duration]);
99
103
  var onLoadedMetadata = function onLoadedMetadata() {
@@ -319,7 +323,7 @@ var ReactAudioPlayerInner = function ReactAudioPlayerInner(props) {
319
323
  // references
320
324
  var audioPlayerRef = (_props$audioPlayerRef = props.audioPlayerRef) !== null && _props$audioPlayerRef !== void 0 ? _props$audioPlayerRef : React.useRef(); // reference our audio component
321
325
  var progressBarRef = (_props$progressBarRef = props.progressBarRef) !== null && _props$progressBarRef !== void 0 ? _props$progressBarRef : React.useRef(); // reference our progress bar
322
-
326
+ var hasInitializedRef = React.useRef(false);
323
327
  var customStyles = props ? props.style : '';
324
328
  var title = props.title,
325
329
  audioSrc = props.audioSrc,
@@ -345,16 +349,23 @@ var ReactAudioPlayerInner = function ReactAudioPlayerInner(props) {
345
349
  var audioDuration = duration && !isNaN(duration) && calculateTime(duration);
346
350
  var formatDuration = duration && !isNaN(duration) && audioDuration && formatCalculateTime(audioDuration);
347
351
 
348
- // Reload audio when audioSrc changes
349
- // Use JSON.stringify to handle array comparisons by value instead of reference
352
+ // Reload audio when audioSrc changes.
353
+ // Skip load() on initial mount calling it pre-buffers live streams so that
354
+ // by the time the user clicks play the seekable window has advanced and
355
+ // segments are stale. On first play the browser fetches the live edge
356
+ // naturally. On subsequent src changes we do call load() to reset the element.
357
+ // Use JSON.stringify to handle array comparisons by value instead of reference.
350
358
  React.useEffect(function () {
351
359
  if (audioPlayerRef.current && audioSrc) {
352
- resetDuration === null || resetDuration === void 0 ? void 0 : resetDuration();
353
- try {
354
- audioPlayerRef.current.load();
355
- } catch (err) {
356
- console.warn('Failed to reload audio source:', err);
360
+ if (hasInitializedRef.current) {
361
+ resetDuration === null || resetDuration === void 0 ? void 0 : resetDuration();
362
+ try {
363
+ audioPlayerRef.current.load();
364
+ } catch (err) {
365
+ console.warn('Failed to reload audio source:', err);
366
+ }
357
367
  }
368
+ hasInitializedRef.current = true;
358
369
  }
359
370
  }, [JSON.stringify(audioSrc)]);
360
371
 
@@ -25,15 +25,15 @@ function _iterableToArrayLimit(r, l) {
25
25
  i,
26
26
  u,
27
27
  a = [],
28
- f = !0,
29
- o = !1;
28
+ f = true,
29
+ o = false;
30
30
  try {
31
31
  if (i = (t = t.call(r)).next, 0 === l) {
32
32
  if (Object(t) !== t) return;
33
33
  f = !1;
34
34
  } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
35
35
  } catch (r) {
36
- o = !0, n = r;
36
+ o = true, n = r;
37
37
  } finally {
38
38
  try {
39
39
  if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
@@ -89,9 +89,13 @@ var useAudioPlayer = function useAudioPlayer(audioRef, progressBarRef, volumeCtr
89
89
  }
90
90
  }, [currentTime]);
91
91
  useEffect(function () {
92
- // Cancel RAF loop if duration changes to Infinity (live stream metadata loaded)
93
- if (duration === Infinity && animationRef.current) {
92
+ if (duration === Infinity) {
93
+ // Cancel RAF loop for live streams
94
+ if (animationRef.current) window.cancelAnimationFrame(animationRef.current);
95
+ } else if (duration && !isNaN(duration) && progressBarRef.current && audioRef.current && !audioRef.current.paused) {
96
+ // play() was called before metadata loaded — progressBarRef is now mounted, start loop
94
97
  window.cancelAnimationFrame(animationRef.current);
98
+ animationRef.current = window.requestAnimationFrame(_whilePlaying);
95
99
  }
96
100
  }, [duration]);
97
101
  var onLoadedMetadata = function onLoadedMetadata() {
@@ -317,7 +321,7 @@ var ReactAudioPlayerInner = function ReactAudioPlayerInner(props) {
317
321
  // references
318
322
  var audioPlayerRef = (_props$audioPlayerRef = props.audioPlayerRef) !== null && _props$audioPlayerRef !== void 0 ? _props$audioPlayerRef : useRef(); // reference our audio component
319
323
  var progressBarRef = (_props$progressBarRef = props.progressBarRef) !== null && _props$progressBarRef !== void 0 ? _props$progressBarRef : useRef(); // reference our progress bar
320
-
324
+ var hasInitializedRef = useRef(false);
321
325
  var customStyles = props ? props.style : '';
322
326
  var title = props.title,
323
327
  audioSrc = props.audioSrc,
@@ -343,16 +347,23 @@ var ReactAudioPlayerInner = function ReactAudioPlayerInner(props) {
343
347
  var audioDuration = duration && !isNaN(duration) && calculateTime(duration);
344
348
  var formatDuration = duration && !isNaN(duration) && audioDuration && formatCalculateTime(audioDuration);
345
349
 
346
- // Reload audio when audioSrc changes
347
- // Use JSON.stringify to handle array comparisons by value instead of reference
350
+ // Reload audio when audioSrc changes.
351
+ // Skip load() on initial mount calling it pre-buffers live streams so that
352
+ // by the time the user clicks play the seekable window has advanced and
353
+ // segments are stale. On first play the browser fetches the live edge
354
+ // naturally. On subsequent src changes we do call load() to reset the element.
355
+ // Use JSON.stringify to handle array comparisons by value instead of reference.
348
356
  useEffect(function () {
349
357
  if (audioPlayerRef.current && audioSrc) {
350
- resetDuration === null || resetDuration === void 0 ? void 0 : resetDuration();
351
- try {
352
- audioPlayerRef.current.load();
353
- } catch (err) {
354
- console.warn('Failed to reload audio source:', err);
358
+ if (hasInitializedRef.current) {
359
+ resetDuration === null || resetDuration === void 0 ? void 0 : resetDuration();
360
+ try {
361
+ audioPlayerRef.current.load();
362
+ } catch (err) {
363
+ console.warn('Failed to reload audio source:', err);
364
+ }
355
365
  }
366
+ hasInitializedRef.current = true;
356
367
  }
357
368
  }, [JSON.stringify(audioSrc)]);
358
369
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apm-react-audio-player",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "author": "Jason Phan <jphan@mpr.org>",
5
5
  "license": "MIT",
6
6
  "private": false,