@xhub-reels/sdk 0.1.14 → 0.1.17
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/README.md +11 -11
- package/dist/index.cjs +360 -280
- package/dist/index.d.cts +93 -24
- package/dist/index.d.ts +93 -24
- package/dist/index.js +360 -281
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -827,6 +827,21 @@ var ResourceGovernor = class {
|
|
|
827
827
|
isPreloading(index) {
|
|
828
828
|
return this.store.getState().preloadQueue.includes(index);
|
|
829
829
|
}
|
|
830
|
+
/**
|
|
831
|
+
* Returns the buffer tier (1–4) for a given index.
|
|
832
|
+
* - 1: Active (playing, 10s buffer)
|
|
833
|
+
* - 2: Hot (±bufferWindow, 2s buffer, instant swap)
|
|
834
|
+
* - 3: Warm (manifest + 1 segment, ~300ms show)
|
|
835
|
+
* - 4: Cold (preload queue — manifest in HTTP cache, no DOM)
|
|
836
|
+
*/
|
|
837
|
+
getTier(index) {
|
|
838
|
+
const { focusedIndex, activeAllocations, warmAllocations, preloadQueue } = this.store.getState();
|
|
839
|
+
if (index === focusedIndex) return 1;
|
|
840
|
+
if (activeAllocations.has(index)) return 2;
|
|
841
|
+
if (warmAllocations.has(index)) return 3;
|
|
842
|
+
if (preloadQueue.includes(index)) return 4;
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
830
845
|
getActiveAllocations() {
|
|
831
846
|
return [...this.store.getState().activeAllocations];
|
|
832
847
|
}
|
|
@@ -899,7 +914,9 @@ function usePointerGesture(config = {}) {
|
|
|
899
914
|
containerSize,
|
|
900
915
|
dragThresholdRatio = 0.5,
|
|
901
916
|
onSnap,
|
|
902
|
-
onBounceBack
|
|
917
|
+
onBounceBack,
|
|
918
|
+
onDragStart,
|
|
919
|
+
onDragEnd
|
|
903
920
|
} = config;
|
|
904
921
|
const isDraggingRef = useRef(false);
|
|
905
922
|
const dragOffsetRef = useRef(0);
|
|
@@ -916,6 +933,8 @@ function usePointerGesture(config = {}) {
|
|
|
916
933
|
const onDragThresholdRef = useRef(onDragThreshold);
|
|
917
934
|
const onSnapRef = useRef(onSnap);
|
|
918
935
|
const onBounceBackRef = useRef(onBounceBack);
|
|
936
|
+
const onDragStartRef = useRef(onDragStart);
|
|
937
|
+
const onDragEndRef = useRef(onDragEnd);
|
|
919
938
|
const disabledRef = useRef(disabled);
|
|
920
939
|
const containerSizeRef = useRef(containerSize);
|
|
921
940
|
const dragThresholdRatioRef = useRef(dragThresholdRatio);
|
|
@@ -924,6 +943,8 @@ function usePointerGesture(config = {}) {
|
|
|
924
943
|
onDragThresholdRef.current = onDragThreshold;
|
|
925
944
|
onSnapRef.current = onSnap;
|
|
926
945
|
onBounceBackRef.current = onBounceBack;
|
|
946
|
+
onDragStartRef.current = onDragStart;
|
|
947
|
+
onDragEndRef.current = onDragEnd;
|
|
927
948
|
disabledRef.current = disabled;
|
|
928
949
|
containerSizeRef.current = containerSize;
|
|
929
950
|
dragThresholdRatioRef.current = dragThresholdRatio;
|
|
@@ -990,6 +1011,7 @@ function usePointerGesture(config = {}) {
|
|
|
990
1011
|
window.removeEventListener("pointermove", handlePointerMove);
|
|
991
1012
|
window.removeEventListener("pointerup", handlePointerUp);
|
|
992
1013
|
window.removeEventListener("pointercancel", handlePointerUp);
|
|
1014
|
+
onDragEndRef.current?.();
|
|
993
1015
|
const offset = dragOffsetRef.current;
|
|
994
1016
|
const velocity = velocityRef.current;
|
|
995
1017
|
const shouldSnap = Math.abs(velocity) > velocityThreshold || Math.abs(offset) > distanceThreshold;
|
|
@@ -1021,6 +1043,7 @@ function usePointerGesture(config = {}) {
|
|
|
1021
1043
|
lastTimeRef.current = performance.now();
|
|
1022
1044
|
velocityRef.current = 0;
|
|
1023
1045
|
dragOffsetRef.current = 0;
|
|
1046
|
+
onDragStartRef.current?.();
|
|
1024
1047
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
1025
1048
|
window.addEventListener("pointermove", handlePointerMove, { passive: true });
|
|
1026
1049
|
window.addEventListener("pointerup", handlePointerUp);
|
|
@@ -1238,6 +1261,7 @@ function useResource() {
|
|
|
1238
1261
|
const networkType = useResourceSelector((s) => s.networkType);
|
|
1239
1262
|
const isActive = useResourceSelector((s) => s.isActive);
|
|
1240
1263
|
const prefetchIndex = useResourceSelector((s) => s.prefetchIndex);
|
|
1264
|
+
const preloadQueue = useResourceSelector((s) => s.preloadQueue);
|
|
1241
1265
|
const activeIndices = useMemo(() => [...activeAllocations], [activeAllocations]);
|
|
1242
1266
|
const warmIndices = useMemo(() => [...warmAllocations], [warmAllocations]);
|
|
1243
1267
|
const setFocusedIndex = useCallback(
|
|
@@ -1268,6 +1292,10 @@ function useResource() {
|
|
|
1268
1292
|
(i) => resourceGovernor.setPrefetchIndex(i),
|
|
1269
1293
|
[resourceGovernor]
|
|
1270
1294
|
);
|
|
1295
|
+
const getTier = useCallback(
|
|
1296
|
+
(index) => resourceGovernor.getTier(index),
|
|
1297
|
+
[resourceGovernor]
|
|
1298
|
+
);
|
|
1271
1299
|
return {
|
|
1272
1300
|
activeIndices,
|
|
1273
1301
|
warmIndices,
|
|
@@ -1276,13 +1304,15 @@ function useResource() {
|
|
|
1276
1304
|
networkType,
|
|
1277
1305
|
isActive,
|
|
1278
1306
|
prefetchIndex,
|
|
1307
|
+
preloadQueue,
|
|
1279
1308
|
setFocusedIndex,
|
|
1280
1309
|
setFocusedIndexImmediate,
|
|
1281
1310
|
setTotalItems,
|
|
1282
1311
|
shouldRenderVideo,
|
|
1283
1312
|
isAllocated,
|
|
1284
1313
|
isWarmAllocated,
|
|
1285
|
-
setPrefetchIndex
|
|
1314
|
+
setPrefetchIndex,
|
|
1315
|
+
getTier
|
|
1286
1316
|
};
|
|
1287
1317
|
}
|
|
1288
1318
|
var ACTIVE_HLS_DEFAULTS = {
|
|
@@ -1358,18 +1388,9 @@ function mapHlsError(data) {
|
|
|
1358
1388
|
}
|
|
1359
1389
|
function useHls(options) {
|
|
1360
1390
|
const { src, videoRef, isActive, isPrefetch, bufferTier = "active", hlsConfig, onError } = options;
|
|
1361
|
-
const
|
|
1362
|
-
const
|
|
1363
|
-
|
|
1364
|
-
const hlsSupported = Hls.isSupported();
|
|
1365
|
-
const native = supportsNativeHls();
|
|
1366
|
-
setIsHlsJs(hlsSupported && !native);
|
|
1367
|
-
setIsNativeHls(native);
|
|
1368
|
-
}, []);
|
|
1369
|
-
const isHlsJsRef = useRef(false);
|
|
1370
|
-
const isNativeRef = useRef(false);
|
|
1371
|
-
isHlsJsRef.current = isHlsJs;
|
|
1372
|
-
isNativeRef.current = isNativeHls;
|
|
1391
|
+
const isHlsSupported = typeof window !== "undefined" && Hls.isSupported();
|
|
1392
|
+
const isNative = supportsNativeHls();
|
|
1393
|
+
const isHlsJs = isHlsSupported && !isNative;
|
|
1373
1394
|
const [isReady, setIsReady] = useState(false);
|
|
1374
1395
|
const hlsRef = useRef(null);
|
|
1375
1396
|
const onErrorRef = useRef(onError);
|
|
@@ -1394,18 +1415,7 @@ function useHls(options) {
|
|
|
1394
1415
|
currentSrcRef.current = void 0;
|
|
1395
1416
|
return;
|
|
1396
1417
|
}
|
|
1397
|
-
const isNative = isNativeRef.current;
|
|
1398
|
-
const isHlsSupported = isHlsJsRef.current;
|
|
1399
1418
|
if (!isActive && !isPrefetch) {
|
|
1400
|
-
if (isNative) {
|
|
1401
|
-
if (video.src) {
|
|
1402
|
-
video.removeAttribute("src");
|
|
1403
|
-
video.load();
|
|
1404
|
-
}
|
|
1405
|
-
setIsReady(false);
|
|
1406
|
-
currentSrcRef.current = void 0;
|
|
1407
|
-
return;
|
|
1408
|
-
}
|
|
1409
1419
|
destroy();
|
|
1410
1420
|
setIsReady(false);
|
|
1411
1421
|
canPlayFiredRef.current = false;
|
|
@@ -1413,45 +1423,40 @@ function useHls(options) {
|
|
|
1413
1423
|
return;
|
|
1414
1424
|
}
|
|
1415
1425
|
if (isNative) {
|
|
1416
|
-
if (
|
|
1417
|
-
|
|
1418
|
-
setIsReady(true);
|
|
1419
|
-
return void 0;
|
|
1420
|
-
}
|
|
1421
|
-
const handleCanPlayReuse = () => setIsReady(true);
|
|
1422
|
-
video.addEventListener("canplay", handleCanPlayReuse, { once: true });
|
|
1423
|
-
video.addEventListener("loadeddata", handleCanPlayReuse, { once: true });
|
|
1424
|
-
video.addEventListener("playing", handleCanPlayReuse, { once: true });
|
|
1425
|
-
if (video.readyState < HTMLMediaElement.HAVE_CURRENT_DATA) {
|
|
1426
|
-
video.load();
|
|
1427
|
-
}
|
|
1428
|
-
return () => {
|
|
1429
|
-
video.removeEventListener("canplay", handleCanPlayReuse);
|
|
1430
|
-
video.removeEventListener("loadeddata", handleCanPlayReuse);
|
|
1431
|
-
video.removeEventListener("playing", handleCanPlayReuse);
|
|
1432
|
-
};
|
|
1433
|
-
}
|
|
1434
|
-
video.src = src;
|
|
1435
|
-
currentSrcRef.current = src;
|
|
1436
|
-
if (!isActive) {
|
|
1426
|
+
if (video.src !== src) {
|
|
1427
|
+
video.src = src;
|
|
1437
1428
|
video.load();
|
|
1438
1429
|
}
|
|
1439
|
-
if (video.
|
|
1430
|
+
if (!video.hasAttribute("webkit-playsinline")) {
|
|
1431
|
+
video.setAttribute("webkit-playsinline", "");
|
|
1432
|
+
}
|
|
1433
|
+
if (video.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA) {
|
|
1440
1434
|
setIsReady(true);
|
|
1441
|
-
|
|
1435
|
+
currentSrcRef.current = src;
|
|
1436
|
+
return;
|
|
1442
1437
|
}
|
|
1443
1438
|
setIsReady(false);
|
|
1444
|
-
|
|
1439
|
+
canPlayFiredRef.current = false;
|
|
1440
|
+
currentSrcRef.current = src;
|
|
1441
|
+
const handleCanPlay2 = () => {
|
|
1442
|
+
canPlayFiredRef.current = true;
|
|
1443
|
+
setIsReady(true);
|
|
1444
|
+
};
|
|
1445
|
+
const handleLoadedData = () => {
|
|
1446
|
+
if (!canPlayFiredRef.current) {
|
|
1447
|
+
canPlayFiredRef.current = true;
|
|
1448
|
+
setIsReady(true);
|
|
1449
|
+
}
|
|
1450
|
+
};
|
|
1445
1451
|
video.addEventListener("canplay", handleCanPlay2, { once: true });
|
|
1446
|
-
video.addEventListener("loadeddata",
|
|
1447
|
-
video.addEventListener("playing", handleCanPlay2, { once: true });
|
|
1452
|
+
video.addEventListener("loadeddata", handleLoadedData, { once: true });
|
|
1448
1453
|
return () => {
|
|
1449
1454
|
video.removeEventListener("canplay", handleCanPlay2);
|
|
1450
|
-
video.removeEventListener("loadeddata",
|
|
1451
|
-
video.removeEventListener("playing", handleCanPlay2);
|
|
1455
|
+
video.removeEventListener("loadeddata", handleLoadedData);
|
|
1452
1456
|
};
|
|
1453
1457
|
}
|
|
1454
1458
|
if (!isHlsSupported) {
|
|
1459
|
+
onErrorRef.current?.("UNKNOWN", "HLS playback not supported in this browser");
|
|
1455
1460
|
return;
|
|
1456
1461
|
}
|
|
1457
1462
|
if (hlsRef.current && currentSrcRef.current === src) {
|
|
@@ -1515,7 +1520,7 @@ function useHls(options) {
|
|
|
1515
1520
|
currentSrcRef.current = void 0;
|
|
1516
1521
|
}
|
|
1517
1522
|
};
|
|
1518
|
-
}, [src, isActive, isPrefetch
|
|
1523
|
+
}, [src, isActive, isPrefetch]);
|
|
1519
1524
|
useEffect(() => {
|
|
1520
1525
|
const hls = hlsRef.current;
|
|
1521
1526
|
if (!hls) {
|
|
@@ -1531,10 +1536,15 @@ function useHls(options) {
|
|
|
1531
1536
|
for (const key of configKeys) {
|
|
1532
1537
|
hlsAnyConfig[key] = newConfig[key];
|
|
1533
1538
|
}
|
|
1539
|
+
if (prevTier === "warm" && bufferTier === "active") {
|
|
1540
|
+
try {
|
|
1541
|
+
hls.startLoad();
|
|
1542
|
+
} catch {
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1534
1545
|
}, [bufferTier]);
|
|
1535
1546
|
return {
|
|
1536
1547
|
isHlsJs,
|
|
1537
|
-
isNativeHls,
|
|
1538
1548
|
isReady,
|
|
1539
1549
|
destroy
|
|
1540
1550
|
};
|
|
@@ -1653,6 +1663,60 @@ function skeletonCircle(size) {
|
|
|
1653
1663
|
background: "rgba(255,255,255,0.1)"
|
|
1654
1664
|
};
|
|
1655
1665
|
}
|
|
1666
|
+
function DefaultPauseAction() {
|
|
1667
|
+
return /* @__PURE__ */ jsx(
|
|
1668
|
+
"div",
|
|
1669
|
+
{
|
|
1670
|
+
style: {
|
|
1671
|
+
width: 72,
|
|
1672
|
+
height: 72,
|
|
1673
|
+
borderRadius: "50%",
|
|
1674
|
+
background: "rgba(0, 0, 0, 0.55)",
|
|
1675
|
+
display: "flex",
|
|
1676
|
+
alignItems: "center",
|
|
1677
|
+
justifyContent: "center",
|
|
1678
|
+
pointerEvents: "none",
|
|
1679
|
+
// Inset the triangle visually — triangles look off-center without this
|
|
1680
|
+
paddingLeft: 6
|
|
1681
|
+
},
|
|
1682
|
+
children: /* @__PURE__ */ jsx(
|
|
1683
|
+
"svg",
|
|
1684
|
+
{
|
|
1685
|
+
width: "32",
|
|
1686
|
+
height: "32",
|
|
1687
|
+
viewBox: "0 0 32 32",
|
|
1688
|
+
fill: "none",
|
|
1689
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1690
|
+
children: /* @__PURE__ */ jsx(
|
|
1691
|
+
"path",
|
|
1692
|
+
{
|
|
1693
|
+
d: "M8 5.5L27 16L8 26.5V5.5Z",
|
|
1694
|
+
fill: "white"
|
|
1695
|
+
}
|
|
1696
|
+
)
|
|
1697
|
+
}
|
|
1698
|
+
)
|
|
1699
|
+
}
|
|
1700
|
+
);
|
|
1701
|
+
}
|
|
1702
|
+
var PLAY_AHEAD_MAX_CONCURRENT = 2;
|
|
1703
|
+
var _playAheadActive = 0;
|
|
1704
|
+
var _playAheadQueue = [];
|
|
1705
|
+
function acquirePlayAhead() {
|
|
1706
|
+
if (_playAheadActive < PLAY_AHEAD_MAX_CONCURRENT) {
|
|
1707
|
+
_playAheadActive++;
|
|
1708
|
+
return Promise.resolve();
|
|
1709
|
+
}
|
|
1710
|
+
return new Promise((resolve) => _playAheadQueue.push(resolve));
|
|
1711
|
+
}
|
|
1712
|
+
function releasePlayAhead() {
|
|
1713
|
+
_playAheadActive = Math.max(0, _playAheadActive - 1);
|
|
1714
|
+
const next = _playAheadQueue.shift();
|
|
1715
|
+
if (next) {
|
|
1716
|
+
_playAheadActive++;
|
|
1717
|
+
next();
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1656
1720
|
function VideoSlot({
|
|
1657
1721
|
item,
|
|
1658
1722
|
index,
|
|
@@ -1662,10 +1726,11 @@ function VideoSlot({
|
|
|
1662
1726
|
bufferTier,
|
|
1663
1727
|
isMuted,
|
|
1664
1728
|
onToggleMute,
|
|
1729
|
+
onAutoplayBlocked,
|
|
1665
1730
|
showFps = false,
|
|
1666
1731
|
renderOverlay,
|
|
1667
1732
|
renderActions,
|
|
1668
|
-
|
|
1733
|
+
renderPauseAction
|
|
1669
1734
|
}) {
|
|
1670
1735
|
const { optimisticManager, adapters } = useSDK();
|
|
1671
1736
|
if (!isVideoItem(item)) {
|
|
@@ -1698,10 +1763,11 @@ function VideoSlot({
|
|
|
1698
1763
|
bufferTier,
|
|
1699
1764
|
isMuted,
|
|
1700
1765
|
onToggleMute,
|
|
1766
|
+
onAutoplayBlocked,
|
|
1701
1767
|
showFps,
|
|
1702
1768
|
renderOverlay,
|
|
1703
1769
|
renderActions,
|
|
1704
|
-
|
|
1770
|
+
renderPauseAction,
|
|
1705
1771
|
optimisticManager,
|
|
1706
1772
|
adapters
|
|
1707
1773
|
}
|
|
@@ -1716,10 +1782,11 @@ function VideoSlotInner({
|
|
|
1716
1782
|
bufferTier,
|
|
1717
1783
|
isMuted,
|
|
1718
1784
|
onToggleMute,
|
|
1785
|
+
onAutoplayBlocked,
|
|
1719
1786
|
showFps,
|
|
1720
1787
|
renderOverlay,
|
|
1721
1788
|
renderActions,
|
|
1722
|
-
|
|
1789
|
+
renderPauseAction,
|
|
1723
1790
|
optimisticManager,
|
|
1724
1791
|
adapters
|
|
1725
1792
|
}) {
|
|
@@ -1730,7 +1797,7 @@ function VideoSlotInner({
|
|
|
1730
1797
|
const isHlsSource = sourceType === "hls";
|
|
1731
1798
|
const hlsSrc = isHlsSource && shouldLoadSrc ? src : void 0;
|
|
1732
1799
|
const mp4Src = !isHlsSource && shouldLoadSrc ? src : void 0;
|
|
1733
|
-
const { isReady: hlsReady
|
|
1800
|
+
const { isReady: hlsReady } = useHls({
|
|
1734
1801
|
src: hlsSrc,
|
|
1735
1802
|
videoRef,
|
|
1736
1803
|
isActive,
|
|
@@ -1769,9 +1836,7 @@ function VideoSlotInner({
|
|
|
1769
1836
|
}, [mp4Src, isActive, isPrefetch, isPreloaded, isHlsSource]);
|
|
1770
1837
|
const isReady = isHlsSource ? hlsReady : mp4Ready;
|
|
1771
1838
|
const [hasPlayedAhead, setHasPlayedAhead] = useState(false);
|
|
1772
|
-
const canPlayAhead = isHlsSource && !isNativeHls;
|
|
1773
1839
|
useEffect(() => {
|
|
1774
|
-
if (!canPlayAhead) return;
|
|
1775
1840
|
const video = videoRef.current;
|
|
1776
1841
|
if (!video) return;
|
|
1777
1842
|
if (isActive || !isReady) return;
|
|
@@ -1779,180 +1844,145 @@ function VideoSlotInner({
|
|
|
1779
1844
|
const prevMuted = video.muted;
|
|
1780
1845
|
video.muted = true;
|
|
1781
1846
|
let cancelled = false;
|
|
1782
|
-
let rafId = null;
|
|
1783
|
-
let vfcHandle = null;
|
|
1784
|
-
const pauseAfterDecode = () => {
|
|
1785
|
-
if (cancelled) return;
|
|
1786
|
-
video.pause();
|
|
1787
|
-
video.currentTime = 0;
|
|
1788
|
-
video.muted = prevMuted;
|
|
1789
|
-
setHasPlayedAhead(true);
|
|
1790
|
-
};
|
|
1791
1847
|
const doPlayAhead = async () => {
|
|
1848
|
+
await acquirePlayAhead();
|
|
1792
1849
|
try {
|
|
1793
1850
|
await video.play();
|
|
1794
|
-
if (cancelled)
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
pauseAfterDecode();
|
|
1799
|
-
});
|
|
1800
|
-
} else {
|
|
1801
|
-
rafId = requestAnimationFrame(() => {
|
|
1802
|
-
rafId = requestAnimationFrame(() => {
|
|
1803
|
-
rafId = null;
|
|
1804
|
-
pauseAfterDecode();
|
|
1805
|
-
});
|
|
1806
|
-
});
|
|
1851
|
+
if (cancelled) {
|
|
1852
|
+
video.pause();
|
|
1853
|
+
releasePlayAhead();
|
|
1854
|
+
return;
|
|
1807
1855
|
}
|
|
1856
|
+
const pauseAfterDecode = () => {
|
|
1857
|
+
video.pause();
|
|
1858
|
+
video.currentTime = 0;
|
|
1859
|
+
video.muted = prevMuted;
|
|
1860
|
+
releasePlayAhead();
|
|
1861
|
+
if (!cancelled) {
|
|
1862
|
+
setHasPlayedAhead(true);
|
|
1863
|
+
}
|
|
1864
|
+
};
|
|
1865
|
+
setTimeout(pauseAfterDecode, 50);
|
|
1808
1866
|
} catch {
|
|
1809
|
-
|
|
1867
|
+
releasePlayAhead();
|
|
1810
1868
|
}
|
|
1811
1869
|
};
|
|
1812
1870
|
doPlayAhead();
|
|
1813
1871
|
return () => {
|
|
1814
1872
|
cancelled = true;
|
|
1815
|
-
if (rafId !== null) {
|
|
1816
|
-
cancelAnimationFrame(rafId);
|
|
1817
|
-
rafId = null;
|
|
1818
|
-
}
|
|
1819
|
-
if (vfcHandle !== null && "cancelVideoFrameCallback" in video) {
|
|
1820
|
-
video.cancelVideoFrameCallback(vfcHandle);
|
|
1821
|
-
vfcHandle = null;
|
|
1822
|
-
}
|
|
1823
1873
|
};
|
|
1824
|
-
}, [
|
|
1874
|
+
}, [isActive, isReady, hasPlayedAhead]);
|
|
1825
1875
|
useEffect(() => {
|
|
1826
1876
|
setHasPlayedAhead(false);
|
|
1827
1877
|
}, [src]);
|
|
1828
1878
|
const wasActiveRef = useRef(false);
|
|
1879
|
+
const [isManuallyPaused, setIsManuallyPaused] = useState(false);
|
|
1829
1880
|
useEffect(() => {
|
|
1830
1881
|
const video = videoRef.current;
|
|
1831
1882
|
if (!video) return;
|
|
1832
1883
|
let onReady = null;
|
|
1833
|
-
let
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
const startPlay = () => {
|
|
1838
|
-
if (onReady) {
|
|
1839
|
-
video.removeEventListener("canplay", onReady);
|
|
1840
|
-
video.removeEventListener("loadeddata", onReady);
|
|
1841
|
-
video.removeEventListener("playing", onReady);
|
|
1842
|
-
onReady = null;
|
|
1843
|
-
}
|
|
1844
|
-
if (fallbackTimerId !== null) {
|
|
1845
|
-
clearTimeout(fallbackTimerId);
|
|
1846
|
-
fallbackTimerId = null;
|
|
1847
|
-
}
|
|
1848
|
-
if (pollId !== null) {
|
|
1849
|
-
clearInterval(pollId);
|
|
1850
|
-
pollId = null;
|
|
1851
|
-
}
|
|
1884
|
+
let cancelled = false;
|
|
1885
|
+
const attemptPlay = () => {
|
|
1886
|
+
if (cancelled) return;
|
|
1887
|
+
if (isMuted) {
|
|
1852
1888
|
video.muted = true;
|
|
1853
|
-
video.play().
|
|
1854
|
-
video.muted = isMuted;
|
|
1855
|
-
}).catch(() => {
|
|
1856
|
-
video.muted = isMuted;
|
|
1889
|
+
video.play().catch(() => {
|
|
1857
1890
|
});
|
|
1858
|
-
};
|
|
1859
|
-
if (video.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {
|
|
1860
|
-
startPlay();
|
|
1861
1891
|
} else {
|
|
1862
|
-
|
|
1863
|
-
video.
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
if (
|
|
1873
|
-
|
|
1874
|
-
|
|
1892
|
+
video.muted = false;
|
|
1893
|
+
video.play().then(() => {
|
|
1894
|
+
if (cancelled) {
|
|
1895
|
+
video.pause();
|
|
1896
|
+
}
|
|
1897
|
+
}).catch((err) => {
|
|
1898
|
+
if (cancelled) return;
|
|
1899
|
+
if (err.name === "NotAllowedError") {
|
|
1900
|
+
video.muted = true;
|
|
1901
|
+
video.play().then(() => {
|
|
1902
|
+
if (cancelled) {
|
|
1903
|
+
video.pause();
|
|
1904
|
+
return;
|
|
1875
1905
|
}
|
|
1876
|
-
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
|
-
}
|
|
1880
|
-
fallbackTimerId = window.setTimeout(() => {
|
|
1881
|
-
fallbackTimerId = null;
|
|
1882
|
-
if (onReady) {
|
|
1883
|
-
startPlay();
|
|
1906
|
+
onAutoplayBlocked?.();
|
|
1907
|
+
}).catch(() => {
|
|
1908
|
+
});
|
|
1884
1909
|
}
|
|
1885
|
-
}
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
};
|
|
1913
|
+
if (isActive && !isManuallyPaused) {
|
|
1914
|
+
wasActiveRef.current = true;
|
|
1915
|
+
if (video.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA) {
|
|
1916
|
+
attemptPlay();
|
|
1917
|
+
} else {
|
|
1918
|
+
onReady = attemptPlay;
|
|
1919
|
+
video.addEventListener("canplay", onReady, { once: true });
|
|
1886
1920
|
}
|
|
1921
|
+
} else if (isActive && isManuallyPaused) {
|
|
1922
|
+
wasActiveRef.current = true;
|
|
1923
|
+
video.pause();
|
|
1887
1924
|
} else if (wasActiveRef.current) {
|
|
1888
1925
|
video.pause();
|
|
1889
1926
|
video.currentTime = 0;
|
|
1890
1927
|
wasActiveRef.current = false;
|
|
1928
|
+
setIsManuallyPaused(false);
|
|
1891
1929
|
setHasPlayedAhead(false);
|
|
1892
1930
|
} else if (!hasPlayedAhead) {
|
|
1893
1931
|
video.pause();
|
|
1894
1932
|
}
|
|
1895
1933
|
return () => {
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
video.removeEventListener("loadeddata", onReady);
|
|
1899
|
-
video.removeEventListener("playing", onReady);
|
|
1900
|
-
}
|
|
1901
|
-
if (fallbackTimerId !== null) {
|
|
1902
|
-
clearTimeout(fallbackTimerId);
|
|
1903
|
-
fallbackTimerId = null;
|
|
1904
|
-
}
|
|
1905
|
-
if (pollId !== null) {
|
|
1906
|
-
clearInterval(pollId);
|
|
1907
|
-
pollId = null;
|
|
1908
|
-
}
|
|
1934
|
+
cancelled = true;
|
|
1935
|
+
if (onReady) video.removeEventListener("canplay", onReady);
|
|
1909
1936
|
};
|
|
1910
|
-
}, [isActive, isMuted, hasPlayedAhead,
|
|
1937
|
+
}, [isActive, isMuted, hasPlayedAhead, isManuallyPaused, onAutoplayBlocked]);
|
|
1911
1938
|
useEffect(() => {
|
|
1912
1939
|
const video = videoRef.current;
|
|
1913
1940
|
if (!video) return;
|
|
1914
|
-
|
|
1915
|
-
video.muted = isMuted;
|
|
1916
|
-
} else {
|
|
1917
|
-
video.muted = true;
|
|
1918
|
-
}
|
|
1941
|
+
video.muted = isActive ? isMuted : true;
|
|
1919
1942
|
}, [isMuted, isActive]);
|
|
1920
|
-
const
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
video.removeEventListener("ended", onEnded);
|
|
1934
|
-
};
|
|
1943
|
+
const showPosterOverlay = !isReady && !hasPlayedAhead;
|
|
1944
|
+
const [showMuteIndicator, setShowMuteIndicator] = useState(false);
|
|
1945
|
+
const muteIndicatorTimer = useRef(null);
|
|
1946
|
+
const handleToggleMute = useCallback(() => {
|
|
1947
|
+
onToggleMute();
|
|
1948
|
+
setShowMuteIndicator(true);
|
|
1949
|
+
if (muteIndicatorTimer.current) clearTimeout(muteIndicatorTimer.current);
|
|
1950
|
+
muteIndicatorTimer.current = setTimeout(() => setShowMuteIndicator(false), 1200);
|
|
1951
|
+
}, [onToggleMute]);
|
|
1952
|
+
const tapStartRef = useRef(null);
|
|
1953
|
+
const TAP_SLOP_PX = 10;
|
|
1954
|
+
const handlePointerDown = useCallback((e) => {
|
|
1955
|
+
tapStartRef.current = { x: e.clientX, y: e.clientY };
|
|
1935
1956
|
}, []);
|
|
1936
|
-
|
|
1937
|
-
if (
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1957
|
+
const handleClick = useCallback((e) => {
|
|
1958
|
+
if (e.button !== 0) return;
|
|
1959
|
+
if (!isActive) return;
|
|
1960
|
+
const start = tapStartRef.current;
|
|
1961
|
+
if (start) {
|
|
1962
|
+
const dx = Math.abs(e.clientX - start.x);
|
|
1963
|
+
const dy = Math.abs(e.clientY - start.y);
|
|
1964
|
+
if (dx > TAP_SLOP_PX || dy > TAP_SLOP_PX) {
|
|
1965
|
+
tapStartRef.current = null;
|
|
1966
|
+
return;
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
tapStartRef.current = null;
|
|
1942
1970
|
const video = videoRef.current;
|
|
1943
|
-
if (!video
|
|
1944
|
-
if (video.paused) {
|
|
1945
|
-
|
|
1971
|
+
if (!video) return;
|
|
1972
|
+
if (video.paused || isManuallyPaused) {
|
|
1973
|
+
setIsManuallyPaused(false);
|
|
1974
|
+
video.muted = true;
|
|
1975
|
+
video.play().then(() => {
|
|
1976
|
+
requestAnimationFrame(() => {
|
|
1977
|
+
video.muted = isMuted;
|
|
1978
|
+
});
|
|
1979
|
+
}).catch(() => {
|
|
1946
1980
|
});
|
|
1947
|
-
setIsPaused(false);
|
|
1948
1981
|
} else {
|
|
1982
|
+
setIsManuallyPaused(true);
|
|
1949
1983
|
video.pause();
|
|
1950
|
-
setIsPaused(true);
|
|
1951
1984
|
}
|
|
1952
|
-
}, [isActive]);
|
|
1953
|
-
useEffect(() => {
|
|
1954
|
-
if (isActive) setIsPaused(false);
|
|
1955
|
-
}, [isActive]);
|
|
1985
|
+
}, [isActive, isManuallyPaused, isMuted]);
|
|
1956
1986
|
const likeDelta = useSyncExternalStore(
|
|
1957
1987
|
optimisticManager.store.subscribe,
|
|
1958
1988
|
() => optimisticManager.getLikeDelta(item.id),
|
|
@@ -1970,12 +2000,36 @@ function VideoSlotInner({
|
|
|
1970
2000
|
followState,
|
|
1971
2001
|
share: () => adapters.interaction?.share?.(item.id),
|
|
1972
2002
|
isMuted,
|
|
1973
|
-
toggleMute:
|
|
1974
|
-
isPaused,
|
|
1975
|
-
togglePause: handleTap,
|
|
2003
|
+
toggleMute: handleToggleMute,
|
|
1976
2004
|
isActive,
|
|
1977
2005
|
index
|
|
1978
|
-
}), [item, likeDelta, followState, isMuted,
|
|
2006
|
+
}), [item, likeDelta, followState, isMuted, isActive, index, optimisticManager, adapters, handleToggleMute]);
|
|
2007
|
+
const pauseActions = useMemo(() => ({
|
|
2008
|
+
...actions,
|
|
2009
|
+
isPaused: isManuallyPaused,
|
|
2010
|
+
togglePlayPause: () => {
|
|
2011
|
+
const video = videoRef.current;
|
|
2012
|
+
if (!video) return;
|
|
2013
|
+
if (isManuallyPaused) {
|
|
2014
|
+
setIsManuallyPaused(false);
|
|
2015
|
+
video.muted = true;
|
|
2016
|
+
video.play().then(() => {
|
|
2017
|
+
requestAnimationFrame(() => {
|
|
2018
|
+
video.muted = isMuted;
|
|
2019
|
+
});
|
|
2020
|
+
}).catch(() => {
|
|
2021
|
+
});
|
|
2022
|
+
} else {
|
|
2023
|
+
setIsManuallyPaused(true);
|
|
2024
|
+
video.pause();
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
}), [actions, isManuallyPaused, isMuted]);
|
|
2028
|
+
useEffect(() => {
|
|
2029
|
+
return () => {
|
|
2030
|
+
if (muteIndicatorTimer.current) clearTimeout(muteIndicatorTimer.current);
|
|
2031
|
+
};
|
|
2032
|
+
}, []);
|
|
1979
2033
|
return /* @__PURE__ */ jsxs(
|
|
1980
2034
|
"div",
|
|
1981
2035
|
{
|
|
@@ -1986,7 +2040,8 @@ function VideoSlotInner({
|
|
|
1986
2040
|
background: "#111",
|
|
1987
2041
|
overflow: "hidden"
|
|
1988
2042
|
},
|
|
1989
|
-
|
|
2043
|
+
onPointerDown: handlePointerDown,
|
|
2044
|
+
onClick: handleClick,
|
|
1990
2045
|
children: [
|
|
1991
2046
|
/* @__PURE__ */ jsx(
|
|
1992
2047
|
"video",
|
|
@@ -1994,9 +2049,8 @@ function VideoSlotInner({
|
|
|
1994
2049
|
ref: videoRef,
|
|
1995
2050
|
src: mp4Src,
|
|
1996
2051
|
loop: true,
|
|
1997
|
-
muted: true,
|
|
2052
|
+
muted: isActive ? isMuted : true,
|
|
1998
2053
|
playsInline: true,
|
|
1999
|
-
autoPlay: isActive,
|
|
2000
2054
|
preload: shouldLoadSrc ? "auto" : "none",
|
|
2001
2055
|
style: {
|
|
2002
2056
|
width: "100%",
|
|
@@ -2023,7 +2077,7 @@ function VideoSlotInner({
|
|
|
2023
2077
|
}
|
|
2024
2078
|
}
|
|
2025
2079
|
),
|
|
2026
|
-
|
|
2080
|
+
showMuteIndicator && /* @__PURE__ */ jsx(
|
|
2027
2081
|
"div",
|
|
2028
2082
|
{
|
|
2029
2083
|
style: {
|
|
@@ -2031,26 +2085,32 @@ function VideoSlotInner({
|
|
|
2031
2085
|
top: "50%",
|
|
2032
2086
|
left: "50%",
|
|
2033
2087
|
transform: "translate(-50%, -50%)",
|
|
2088
|
+
background: "rgba(0,0,0,0.6)",
|
|
2089
|
+
borderRadius: "50%",
|
|
2090
|
+
width: 64,
|
|
2091
|
+
height: 64,
|
|
2092
|
+
display: "flex",
|
|
2093
|
+
alignItems: "center",
|
|
2094
|
+
justifyContent: "center",
|
|
2095
|
+
fontSize: 28,
|
|
2034
2096
|
pointerEvents: "none",
|
|
2035
|
-
|
|
2036
|
-
opacity: 0.3
|
|
2097
|
+
animation: "reels-sdk-fadeInOut 1.2s ease forwards"
|
|
2037
2098
|
},
|
|
2038
|
-
children:
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
)
|
|
2099
|
+
children: isMuted ? "\u{1F507}" : "\u{1F50A}"
|
|
2100
|
+
}
|
|
2101
|
+
),
|
|
2102
|
+
isActive && isManuallyPaused && /* @__PURE__ */ jsx(
|
|
2103
|
+
"div",
|
|
2104
|
+
{
|
|
2105
|
+
style: {
|
|
2106
|
+
position: "absolute",
|
|
2107
|
+
top: "50%",
|
|
2108
|
+
left: "50%",
|
|
2109
|
+
transform: "translate(-50%, -50%)",
|
|
2110
|
+
pointerEvents: "none",
|
|
2111
|
+
animation: "reels-sdk-fadeIn 0.2s ease forwards"
|
|
2112
|
+
},
|
|
2113
|
+
children: renderPauseAction ? renderPauseAction(item, pauseActions) : /* @__PURE__ */ jsx(DefaultPauseAction, {})
|
|
2054
2114
|
}
|
|
2055
2115
|
),
|
|
2056
2116
|
/* @__PURE__ */ jsx(
|
|
@@ -2058,13 +2118,11 @@ function VideoSlotInner({
|
|
|
2058
2118
|
{
|
|
2059
2119
|
style: {
|
|
2060
2120
|
position: "absolute",
|
|
2061
|
-
bottom:
|
|
2121
|
+
bottom: 80,
|
|
2062
2122
|
left: 16,
|
|
2063
2123
|
right: 80,
|
|
2064
|
-
paddingBottom: 16,
|
|
2065
2124
|
pointerEvents: "none",
|
|
2066
|
-
color: "#fff"
|
|
2067
|
-
zIndex: 10
|
|
2125
|
+
color: "#fff"
|
|
2068
2126
|
},
|
|
2069
2127
|
children: renderOverlay ? renderOverlay(item, actions) : /* @__PURE__ */ jsx(DefaultOverlay, { item })
|
|
2070
2128
|
}
|
|
@@ -2072,19 +2130,18 @@ function VideoSlotInner({
|
|
|
2072
2130
|
/* @__PURE__ */ jsx(
|
|
2073
2131
|
"div",
|
|
2074
2132
|
{
|
|
2075
|
-
onClick: (e) => e.stopPropagation(),
|
|
2076
2133
|
style: {
|
|
2077
2134
|
position: "absolute",
|
|
2078
|
-
bottom:
|
|
2135
|
+
bottom: 80,
|
|
2079
2136
|
right: 16,
|
|
2080
|
-
paddingBottom: 16,
|
|
2081
2137
|
display: "flex",
|
|
2082
2138
|
flexDirection: "column",
|
|
2083
2139
|
gap: 20,
|
|
2084
|
-
alignItems: "center"
|
|
2085
|
-
|
|
2086
|
-
|
|
2140
|
+
alignItems: "center"
|
|
2141
|
+
// Actions must be clickable; stop propagation so taps don't
|
|
2142
|
+
// also trigger the video play/pause handler on the container.
|
|
2087
2143
|
},
|
|
2144
|
+
onClick: (e) => e.stopPropagation(),
|
|
2088
2145
|
children: renderActions ? renderActions(item, actions) : /* @__PURE__ */ jsx(DefaultActions, { item, actions })
|
|
2089
2146
|
}
|
|
2090
2147
|
),
|
|
@@ -2134,6 +2191,7 @@ function FpsCounter() {
|
|
|
2134
2191
|
}
|
|
2135
2192
|
);
|
|
2136
2193
|
}
|
|
2194
|
+
var RENDER_WINDOW_RADIUS = 3;
|
|
2137
2195
|
var centerStyle = {
|
|
2138
2196
|
height: "100dvh",
|
|
2139
2197
|
display: "flex",
|
|
@@ -2145,7 +2203,7 @@ var centerStyle = {
|
|
|
2145
2203
|
function ReelsFeed({
|
|
2146
2204
|
renderOverlay,
|
|
2147
2205
|
renderActions,
|
|
2148
|
-
|
|
2206
|
+
renderPauseAction,
|
|
2149
2207
|
renderLoading,
|
|
2150
2208
|
renderEmpty,
|
|
2151
2209
|
renderError: _renderError,
|
|
@@ -2153,21 +2211,24 @@ function ReelsFeed({
|
|
|
2153
2211
|
loadMoreThreshold = 5,
|
|
2154
2212
|
onSlotChange,
|
|
2155
2213
|
gestureConfig,
|
|
2156
|
-
snapConfig
|
|
2214
|
+
snapConfig,
|
|
2215
|
+
initialMuted = true,
|
|
2216
|
+
onAutoplayBlocked
|
|
2157
2217
|
}) {
|
|
2158
2218
|
const { items, loading, loadInitial, loadMore, hasMore } = useFeed();
|
|
2219
|
+
const { adapters } = useSDK();
|
|
2159
2220
|
const {
|
|
2160
|
-
activeIndices,
|
|
2161
|
-
warmIndices,
|
|
2162
2221
|
focusedIndex,
|
|
2163
2222
|
prefetchIndex,
|
|
2223
|
+
preloadQueue,
|
|
2164
2224
|
setFocusedIndexImmediate,
|
|
2165
2225
|
setTotalItems,
|
|
2166
2226
|
shouldRenderVideo,
|
|
2167
2227
|
isWarmAllocated,
|
|
2168
2228
|
setPrefetchIndex
|
|
2169
2229
|
} = useResource();
|
|
2170
|
-
const [isMuted, setIsMuted] = useState(
|
|
2230
|
+
const [isMuted, setIsMuted] = useState(initialMuted);
|
|
2231
|
+
const [isDragMuted, setIsDragMuted] = useState(false);
|
|
2171
2232
|
const containerRef = useRef(null);
|
|
2172
2233
|
const slotCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
2173
2234
|
const activeIndexRef = useRef(0);
|
|
@@ -2183,6 +2244,14 @@ function ReelsFeed({
|
|
|
2183
2244
|
useEffect(() => {
|
|
2184
2245
|
setTotalItems(items.length);
|
|
2185
2246
|
}, [items.length, setTotalItems]);
|
|
2247
|
+
useEffect(() => {
|
|
2248
|
+
for (const idx of preloadQueue) {
|
|
2249
|
+
const item = items[idx];
|
|
2250
|
+
if (item && isVideoItem(item) && item.source.type === "hls") {
|
|
2251
|
+
adapters.videoLoader?.preloadMetadata?.(item.source.url);
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
}, [preloadQueue, items, adapters.videoLoader]);
|
|
2186
2255
|
useEffect(() => {
|
|
2187
2256
|
if (items.length - focusedIndex <= loadMoreThreshold && hasMore && !loading) {
|
|
2188
2257
|
loadMore();
|
|
@@ -2203,7 +2272,7 @@ function ReelsFeed({
|
|
|
2203
2272
|
const observer = new MutationObserver(rebuild);
|
|
2204
2273
|
observer.observe(container, { childList: true, subtree: true });
|
|
2205
2274
|
return () => observer.disconnect();
|
|
2206
|
-
}, [items.length]);
|
|
2275
|
+
}, [items.length, focusedIndex]);
|
|
2207
2276
|
const containerHeight = useRef(
|
|
2208
2277
|
typeof window !== "undefined" ? window.innerHeight : 800
|
|
2209
2278
|
);
|
|
@@ -2294,6 +2363,12 @@ function ReelsFeed({
|
|
|
2294
2363
|
animateBounceBack(targets);
|
|
2295
2364
|
setPrefetchIndex(null);
|
|
2296
2365
|
}, [animateBounceBack, setPrefetchIndex]);
|
|
2366
|
+
const handleDragStart = useCallback(() => {
|
|
2367
|
+
setIsDragMuted(true);
|
|
2368
|
+
}, []);
|
|
2369
|
+
const handleDragEnd = useCallback(() => {
|
|
2370
|
+
setTimeout(() => setIsDragMuted(false), 50);
|
|
2371
|
+
}, []);
|
|
2297
2372
|
const { bind } = usePointerGesture({
|
|
2298
2373
|
axis: "y",
|
|
2299
2374
|
velocityThreshold: gestureConfig?.velocityThreshold ?? 0.3,
|
|
@@ -2306,7 +2381,9 @@ function ReelsFeed({
|
|
|
2306
2381
|
},
|
|
2307
2382
|
onDragThreshold: handleDragThreshold,
|
|
2308
2383
|
onSnap: handleSnap,
|
|
2309
|
-
onBounceBack: handleBounceBack
|
|
2384
|
+
onBounceBack: handleBounceBack,
|
|
2385
|
+
onDragStart: handleDragStart,
|
|
2386
|
+
onDragEnd: handleDragEnd
|
|
2310
2387
|
});
|
|
2311
2388
|
const getInitialTransformPx = useCallback(
|
|
2312
2389
|
(index) => {
|
|
@@ -2348,58 +2425,58 @@ function ReelsFeed({
|
|
|
2348
2425
|
70% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
|
2349
2426
|
100% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
|
|
2350
2427
|
}
|
|
2428
|
+
@keyframes reels-sdk-fadeIn {
|
|
2429
|
+
from { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }
|
|
2430
|
+
to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
|
2431
|
+
}
|
|
2351
2432
|
@keyframes reels-sdk-spin {
|
|
2352
2433
|
to { transform: rotate(360deg); }
|
|
2353
2434
|
}
|
|
2354
2435
|
` }),
|
|
2355
|
-
(() => {
|
|
2356
|
-
const
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2436
|
+
items.map((item, index) => {
|
|
2437
|
+
const distFromFocus = Math.abs(index - focusedIndex);
|
|
2438
|
+
const wrapperStyle = {
|
|
2439
|
+
position: "absolute",
|
|
2440
|
+
inset: 0,
|
|
2441
|
+
contain: "layout style paint",
|
|
2442
|
+
willChange: distFromFocus <= 1 ? "transform" : "auto",
|
|
2443
|
+
transform: getInitialTransformPx(index)
|
|
2444
|
+
};
|
|
2445
|
+
if (distFromFocus > RENDER_WINDOW_RADIUS) {
|
|
2446
|
+
return /* @__PURE__ */ jsx("div", { "data-slot-index": index, style: wrapperStyle }, item.id);
|
|
2362
2447
|
}
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
renderPauseIndicator
|
|
2396
|
-
}
|
|
2397
|
-
) : null
|
|
2398
|
-
},
|
|
2399
|
-
item.id
|
|
2400
|
-
);
|
|
2401
|
-
});
|
|
2402
|
-
})()
|
|
2448
|
+
const isActive = index === focusedIndex;
|
|
2449
|
+
const isPrefetch = index === prefetchIndex;
|
|
2450
|
+
const isWarm = isWarmAllocated(index);
|
|
2451
|
+
const isVisible = shouldRenderVideo(index) || isPrefetch;
|
|
2452
|
+
const bufferTier = isActive ? "active" : isWarm ? "warm" : "hot";
|
|
2453
|
+
return /* @__PURE__ */ jsx(
|
|
2454
|
+
"div",
|
|
2455
|
+
{
|
|
2456
|
+
"data-slot-index": index,
|
|
2457
|
+
style: wrapperStyle,
|
|
2458
|
+
children: /* @__PURE__ */ jsx(
|
|
2459
|
+
VideoSlot,
|
|
2460
|
+
{
|
|
2461
|
+
item,
|
|
2462
|
+
index,
|
|
2463
|
+
isActive,
|
|
2464
|
+
isPrefetch,
|
|
2465
|
+
isPreloaded: !isActive && !isPrefetch && isVisible,
|
|
2466
|
+
bufferTier,
|
|
2467
|
+
isMuted: isMuted || isDragMuted,
|
|
2468
|
+
onToggleMute: handleToggleMute,
|
|
2469
|
+
onAutoplayBlocked,
|
|
2470
|
+
showFps: showFps && isActive,
|
|
2471
|
+
renderOverlay,
|
|
2472
|
+
renderActions,
|
|
2473
|
+
renderPauseAction
|
|
2474
|
+
}
|
|
2475
|
+
)
|
|
2476
|
+
},
|
|
2477
|
+
item.id
|
|
2478
|
+
);
|
|
2479
|
+
})
|
|
2403
2480
|
]
|
|
2404
2481
|
}
|
|
2405
2482
|
);
|
|
@@ -2654,6 +2731,8 @@ var MockVideoLoader = class {
|
|
|
2654
2731
|
this.preloaded.clear();
|
|
2655
2732
|
this.loading.clear();
|
|
2656
2733
|
}
|
|
2734
|
+
preloadMetadata(_url) {
|
|
2735
|
+
}
|
|
2657
2736
|
};
|
|
2658
2737
|
var MockDataSource = class {
|
|
2659
2738
|
constructor(options = {}) {
|
|
@@ -3023,4 +3102,4 @@ var HttpError = class extends Error {
|
|
|
3023
3102
|
}
|
|
3024
3103
|
};
|
|
3025
3104
|
|
|
3026
|
-
export { DEFAULT_FEED_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_RESOURCE_CONFIG, DefaultActions, DefaultOverlay, DefaultSkeleton, FeedManager, HttpDataSource, HttpError, MockAnalytics, MockCommentAdapter, MockDataSource, MockInteraction, MockLogger, MockNetworkAdapter, MockSessionStorage, MockVideoLoader, OptimisticManager, PlayerEngine, PlayerStatus, ReelsFeed, ReelsProvider, ResourceGovernor, VALID_TRANSITIONS, VideoSlot, canPause, canPlay, canSeek, isArticle, isValidTransition, isVideoItem, useFeed, useFeedSelector, useHls, usePlayer, usePlayerSelector, usePointerGesture, useResource, useResourceSelector, useSDK, useSnapAnimation };
|
|
3105
|
+
export { DEFAULT_FEED_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_RESOURCE_CONFIG, DefaultActions, DefaultOverlay, DefaultPauseAction, DefaultSkeleton, FeedManager, HttpDataSource, HttpError, MockAnalytics, MockCommentAdapter, MockDataSource, MockInteraction, MockLogger, MockNetworkAdapter, MockSessionStorage, MockVideoLoader, OptimisticManager, PlayerEngine, PlayerStatus, ReelsFeed, ReelsProvider, ResourceGovernor, VALID_TRANSITIONS, VideoSlot, canPause, canPlay, canSeek, isArticle, isValidTransition, isVideoItem, useFeed, useFeedSelector, useHls, usePlayer, usePlayerSelector, usePointerGesture, useResource, useResourceSelector, useSDK, useSnapAnimation };
|