@scalemule/nextjs 0.1.22 → 0.1.23
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.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +72 -3
- package/dist/index.mjs +72 -3
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -898,7 +898,7 @@ interface NarrationPlayerProps {
|
|
|
898
898
|
providerLabel?: string;
|
|
899
899
|
narrationLabel?: string;
|
|
900
900
|
refreshing?: boolean;
|
|
901
|
-
onRefresh?: () => void
|
|
901
|
+
onRefresh?: () => void | Promise<void>;
|
|
902
902
|
onPlaybackError?: () => void;
|
|
903
903
|
}
|
|
904
904
|
declare function NarrationPlayer({ audio, className, providerLabel, narrationLabel, refreshing, onRefresh, onPlaybackError, }: NarrationPlayerProps): react_jsx_runtime.JSX.Element | null;
|
package/dist/index.d.ts
CHANGED
|
@@ -898,7 +898,7 @@ interface NarrationPlayerProps {
|
|
|
898
898
|
providerLabel?: string;
|
|
899
899
|
narrationLabel?: string;
|
|
900
900
|
refreshing?: boolean;
|
|
901
|
-
onRefresh?: () => void
|
|
901
|
+
onRefresh?: () => void | Promise<void>;
|
|
902
902
|
onPlaybackError?: () => void;
|
|
903
903
|
}
|
|
904
904
|
declare function NarrationPlayer({ audio, className, providerLabel, narrationLabel, refreshing, onRefresh, onPlaybackError, }: NarrationPlayerProps): react_jsx_runtime.JSX.Element | null;
|
package/dist/index.js
CHANGED
|
@@ -11289,6 +11289,7 @@ function FeedbackWidget(props) {
|
|
|
11289
11289
|
] });
|
|
11290
11290
|
}
|
|
11291
11291
|
var SPEEDS = [1, 1.25, 1.5, 2];
|
|
11292
|
+
var EXPIRY_REFRESH_WINDOW_MS = 3e4;
|
|
11292
11293
|
var styles = {
|
|
11293
11294
|
root: {
|
|
11294
11295
|
borderRadius: "1.75rem",
|
|
@@ -11466,6 +11467,9 @@ function NarrationPlayer({
|
|
|
11466
11467
|
}) {
|
|
11467
11468
|
const audioRef = React.useRef(null);
|
|
11468
11469
|
const scrubRef = React.useRef(null);
|
|
11470
|
+
const pendingResumeRef = React.useRef(false);
|
|
11471
|
+
const pendingResumeTimeRef = React.useRef(null);
|
|
11472
|
+
const recoveredUrlRef = React.useRef(null);
|
|
11469
11473
|
const [playing, setPlaying] = React.useState(false);
|
|
11470
11474
|
const [currentTime, setCurrentTime] = React.useState(0);
|
|
11471
11475
|
const [duration, setDuration] = React.useState(audio.duration_ms ? audio.duration_ms / 1e3 : 0);
|
|
@@ -11480,10 +11484,26 @@ function NarrationPlayer({
|
|
|
11480
11484
|
React.useEffect(() => {
|
|
11481
11485
|
const element = audioRef.current;
|
|
11482
11486
|
if (!element) return;
|
|
11483
|
-
|
|
11487
|
+
recoveredUrlRef.current = null;
|
|
11488
|
+
const resumeTime = pendingResumeTimeRef.current;
|
|
11489
|
+
setCurrentTime(resumeTime ?? 0);
|
|
11484
11490
|
setPlaying(false);
|
|
11485
11491
|
element.pause();
|
|
11486
|
-
|
|
11492
|
+
try {
|
|
11493
|
+
element.currentTime = resumeTime ?? 0;
|
|
11494
|
+
} catch {
|
|
11495
|
+
element.currentTime = 0;
|
|
11496
|
+
}
|
|
11497
|
+
if (pendingResumeRef.current) {
|
|
11498
|
+
pendingResumeRef.current = false;
|
|
11499
|
+
pendingResumeTimeRef.current = null;
|
|
11500
|
+
element.play().catch(() => {
|
|
11501
|
+
setPlaying(false);
|
|
11502
|
+
onPlaybackError?.();
|
|
11503
|
+
});
|
|
11504
|
+
return;
|
|
11505
|
+
}
|
|
11506
|
+
pendingResumeTimeRef.current = null;
|
|
11487
11507
|
}, [audio.url]);
|
|
11488
11508
|
React.useEffect(() => {
|
|
11489
11509
|
const element = audioRef.current;
|
|
@@ -11491,10 +11511,49 @@ function NarrationPlayer({
|
|
|
11491
11511
|
element.playbackRate = speed;
|
|
11492
11512
|
element.preservesPitch = true;
|
|
11493
11513
|
}, [speed]);
|
|
11514
|
+
function isUrlExpiringSoon() {
|
|
11515
|
+
if (!audio.expires_at) {
|
|
11516
|
+
return false;
|
|
11517
|
+
}
|
|
11518
|
+
const expiresAtMs = Date.parse(audio.expires_at);
|
|
11519
|
+
if (!Number.isFinite(expiresAtMs)) {
|
|
11520
|
+
return false;
|
|
11521
|
+
}
|
|
11522
|
+
return expiresAtMs - Date.now() <= EXPIRY_REFRESH_WINDOW_MS;
|
|
11523
|
+
}
|
|
11524
|
+
async function refreshAndResume() {
|
|
11525
|
+
if (!onRefresh || refreshing) {
|
|
11526
|
+
return false;
|
|
11527
|
+
}
|
|
11528
|
+
if (recoveredUrlRef.current === (audio.url ?? null)) {
|
|
11529
|
+
return false;
|
|
11530
|
+
}
|
|
11531
|
+
recoveredUrlRef.current = audio.url ?? null;
|
|
11532
|
+
pendingResumeRef.current = true;
|
|
11533
|
+
pendingResumeTimeRef.current = currentTime;
|
|
11534
|
+
try {
|
|
11535
|
+
await Promise.resolve(onRefresh());
|
|
11536
|
+
return true;
|
|
11537
|
+
} catch {
|
|
11538
|
+
pendingResumeRef.current = false;
|
|
11539
|
+
pendingResumeTimeRef.current = null;
|
|
11540
|
+
onPlaybackError?.();
|
|
11541
|
+
return false;
|
|
11542
|
+
}
|
|
11543
|
+
}
|
|
11494
11544
|
function togglePlayback() {
|
|
11495
11545
|
const element = audioRef.current;
|
|
11496
11546
|
if (!element) return;
|
|
11497
11547
|
if (element.paused) {
|
|
11548
|
+
if (refreshing) {
|
|
11549
|
+
pendingResumeRef.current = true;
|
|
11550
|
+
pendingResumeTimeRef.current = currentTime;
|
|
11551
|
+
return;
|
|
11552
|
+
}
|
|
11553
|
+
if (onRefresh && isUrlExpiringSoon()) {
|
|
11554
|
+
void refreshAndResume();
|
|
11555
|
+
return;
|
|
11556
|
+
}
|
|
11498
11557
|
element.play().catch(() => {
|
|
11499
11558
|
setPlaying(false);
|
|
11500
11559
|
onPlaybackError?.();
|
|
@@ -11537,7 +11596,17 @@ function NarrationPlayer({
|
|
|
11537
11596
|
onPlay: () => setPlaying(true),
|
|
11538
11597
|
onPause: () => setPlaying(false),
|
|
11539
11598
|
onEnded: () => setPlaying(false),
|
|
11540
|
-
onError: () =>
|
|
11599
|
+
onError: () => {
|
|
11600
|
+
if (onRefresh) {
|
|
11601
|
+
void refreshAndResume().then((didRefresh) => {
|
|
11602
|
+
if (!didRefresh) {
|
|
11603
|
+
onPlaybackError?.();
|
|
11604
|
+
}
|
|
11605
|
+
});
|
|
11606
|
+
return;
|
|
11607
|
+
}
|
|
11608
|
+
onPlaybackError?.();
|
|
11609
|
+
}
|
|
11541
11610
|
}
|
|
11542
11611
|
),
|
|
11543
11612
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: styles.layout, children: [
|
package/dist/index.mjs
CHANGED
|
@@ -11269,6 +11269,7 @@ function FeedbackWidget(props) {
|
|
|
11269
11269
|
] });
|
|
11270
11270
|
}
|
|
11271
11271
|
var SPEEDS = [1, 1.25, 1.5, 2];
|
|
11272
|
+
var EXPIRY_REFRESH_WINDOW_MS = 3e4;
|
|
11272
11273
|
var styles = {
|
|
11273
11274
|
root: {
|
|
11274
11275
|
borderRadius: "1.75rem",
|
|
@@ -11446,6 +11447,9 @@ function NarrationPlayer({
|
|
|
11446
11447
|
}) {
|
|
11447
11448
|
const audioRef = useRef(null);
|
|
11448
11449
|
const scrubRef = useRef(null);
|
|
11450
|
+
const pendingResumeRef = useRef(false);
|
|
11451
|
+
const pendingResumeTimeRef = useRef(null);
|
|
11452
|
+
const recoveredUrlRef = useRef(null);
|
|
11449
11453
|
const [playing, setPlaying] = useState(false);
|
|
11450
11454
|
const [currentTime, setCurrentTime] = useState(0);
|
|
11451
11455
|
const [duration, setDuration] = useState(audio.duration_ms ? audio.duration_ms / 1e3 : 0);
|
|
@@ -11460,10 +11464,26 @@ function NarrationPlayer({
|
|
|
11460
11464
|
useEffect(() => {
|
|
11461
11465
|
const element = audioRef.current;
|
|
11462
11466
|
if (!element) return;
|
|
11463
|
-
|
|
11467
|
+
recoveredUrlRef.current = null;
|
|
11468
|
+
const resumeTime = pendingResumeTimeRef.current;
|
|
11469
|
+
setCurrentTime(resumeTime ?? 0);
|
|
11464
11470
|
setPlaying(false);
|
|
11465
11471
|
element.pause();
|
|
11466
|
-
|
|
11472
|
+
try {
|
|
11473
|
+
element.currentTime = resumeTime ?? 0;
|
|
11474
|
+
} catch {
|
|
11475
|
+
element.currentTime = 0;
|
|
11476
|
+
}
|
|
11477
|
+
if (pendingResumeRef.current) {
|
|
11478
|
+
pendingResumeRef.current = false;
|
|
11479
|
+
pendingResumeTimeRef.current = null;
|
|
11480
|
+
element.play().catch(() => {
|
|
11481
|
+
setPlaying(false);
|
|
11482
|
+
onPlaybackError?.();
|
|
11483
|
+
});
|
|
11484
|
+
return;
|
|
11485
|
+
}
|
|
11486
|
+
pendingResumeTimeRef.current = null;
|
|
11467
11487
|
}, [audio.url]);
|
|
11468
11488
|
useEffect(() => {
|
|
11469
11489
|
const element = audioRef.current;
|
|
@@ -11471,10 +11491,49 @@ function NarrationPlayer({
|
|
|
11471
11491
|
element.playbackRate = speed;
|
|
11472
11492
|
element.preservesPitch = true;
|
|
11473
11493
|
}, [speed]);
|
|
11494
|
+
function isUrlExpiringSoon() {
|
|
11495
|
+
if (!audio.expires_at) {
|
|
11496
|
+
return false;
|
|
11497
|
+
}
|
|
11498
|
+
const expiresAtMs = Date.parse(audio.expires_at);
|
|
11499
|
+
if (!Number.isFinite(expiresAtMs)) {
|
|
11500
|
+
return false;
|
|
11501
|
+
}
|
|
11502
|
+
return expiresAtMs - Date.now() <= EXPIRY_REFRESH_WINDOW_MS;
|
|
11503
|
+
}
|
|
11504
|
+
async function refreshAndResume() {
|
|
11505
|
+
if (!onRefresh || refreshing) {
|
|
11506
|
+
return false;
|
|
11507
|
+
}
|
|
11508
|
+
if (recoveredUrlRef.current === (audio.url ?? null)) {
|
|
11509
|
+
return false;
|
|
11510
|
+
}
|
|
11511
|
+
recoveredUrlRef.current = audio.url ?? null;
|
|
11512
|
+
pendingResumeRef.current = true;
|
|
11513
|
+
pendingResumeTimeRef.current = currentTime;
|
|
11514
|
+
try {
|
|
11515
|
+
await Promise.resolve(onRefresh());
|
|
11516
|
+
return true;
|
|
11517
|
+
} catch {
|
|
11518
|
+
pendingResumeRef.current = false;
|
|
11519
|
+
pendingResumeTimeRef.current = null;
|
|
11520
|
+
onPlaybackError?.();
|
|
11521
|
+
return false;
|
|
11522
|
+
}
|
|
11523
|
+
}
|
|
11474
11524
|
function togglePlayback() {
|
|
11475
11525
|
const element = audioRef.current;
|
|
11476
11526
|
if (!element) return;
|
|
11477
11527
|
if (element.paused) {
|
|
11528
|
+
if (refreshing) {
|
|
11529
|
+
pendingResumeRef.current = true;
|
|
11530
|
+
pendingResumeTimeRef.current = currentTime;
|
|
11531
|
+
return;
|
|
11532
|
+
}
|
|
11533
|
+
if (onRefresh && isUrlExpiringSoon()) {
|
|
11534
|
+
void refreshAndResume();
|
|
11535
|
+
return;
|
|
11536
|
+
}
|
|
11478
11537
|
element.play().catch(() => {
|
|
11479
11538
|
setPlaying(false);
|
|
11480
11539
|
onPlaybackError?.();
|
|
@@ -11517,7 +11576,17 @@ function NarrationPlayer({
|
|
|
11517
11576
|
onPlay: () => setPlaying(true),
|
|
11518
11577
|
onPause: () => setPlaying(false),
|
|
11519
11578
|
onEnded: () => setPlaying(false),
|
|
11520
|
-
onError: () =>
|
|
11579
|
+
onError: () => {
|
|
11580
|
+
if (onRefresh) {
|
|
11581
|
+
void refreshAndResume().then((didRefresh) => {
|
|
11582
|
+
if (!didRefresh) {
|
|
11583
|
+
onPlaybackError?.();
|
|
11584
|
+
}
|
|
11585
|
+
});
|
|
11586
|
+
return;
|
|
11587
|
+
}
|
|
11588
|
+
onPlaybackError?.();
|
|
11589
|
+
}
|
|
11521
11590
|
}
|
|
11522
11591
|
),
|
|
11523
11592
|
/* @__PURE__ */ jsxs("div", { style: styles.layout, children: [
|
package/package.json
CHANGED