@xhub-reels/sdk 0.2.11 → 0.2.12
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.cjs +38 -7
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +38 -7
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -444,6 +444,13 @@ var FeedManager = class {
|
|
|
444
444
|
// ═══════════════════════════════════════════
|
|
445
445
|
// PUBLIC API — Prefetch
|
|
446
446
|
// ═══════════════════════════════════════════
|
|
447
|
+
setInitialItems(items) {
|
|
448
|
+
this.prefetchCache = {
|
|
449
|
+
items,
|
|
450
|
+
nextCursor: null,
|
|
451
|
+
timestamp: Date.now()
|
|
452
|
+
};
|
|
453
|
+
}
|
|
447
454
|
async prefetch(ttlMs) {
|
|
448
455
|
if (this.prefetchCache) {
|
|
449
456
|
const ttl = ttlMs ?? this.config.staleTTL;
|
|
@@ -1137,7 +1144,12 @@ function useSnapAnimation(config = {}) {
|
|
|
1137
1144
|
return { animateSnap, animateBounceBack, cancelAnimation };
|
|
1138
1145
|
}
|
|
1139
1146
|
var SDKContext = react.createContext(null);
|
|
1140
|
-
function ReelsProvider({
|
|
1147
|
+
function ReelsProvider({
|
|
1148
|
+
children,
|
|
1149
|
+
adapters,
|
|
1150
|
+
initialItems,
|
|
1151
|
+
debug = false
|
|
1152
|
+
}) {
|
|
1141
1153
|
const logger = adapters.logger;
|
|
1142
1154
|
const sdkRef = react.useRef(null);
|
|
1143
1155
|
const value = react.useMemo(() => {
|
|
@@ -1148,6 +1160,9 @@ function ReelsProvider({ children, adapters, debug = false }) {
|
|
|
1148
1160
|
sdkRef.current.optimisticManager.destroy();
|
|
1149
1161
|
}
|
|
1150
1162
|
const feedManager = new FeedManager(adapters.dataSource, {}, logger);
|
|
1163
|
+
if (initialItems && initialItems.length > 0) {
|
|
1164
|
+
feedManager.setInitialItems(initialItems);
|
|
1165
|
+
}
|
|
1151
1166
|
const playerEngine = new PlayerEngine(
|
|
1152
1167
|
{},
|
|
1153
1168
|
adapters.analytics,
|
|
@@ -1336,10 +1351,11 @@ var ACTIVE_HLS_DEFAULTS = {
|
|
|
1336
1351
|
maxMaxBufferLength: 15,
|
|
1337
1352
|
capLevelToPlayerSize: true,
|
|
1338
1353
|
startLevel: 0,
|
|
1339
|
-
abrEwmaDefaultEstimate:
|
|
1354
|
+
abrEwmaDefaultEstimate: 2e6,
|
|
1340
1355
|
lowLatencyMode: false,
|
|
1341
1356
|
backBufferLength: 5,
|
|
1342
|
-
enableWorker: true
|
|
1357
|
+
enableWorker: true,
|
|
1358
|
+
startFragPrefetch: true
|
|
1343
1359
|
};
|
|
1344
1360
|
var HOT_HLS_DEFAULTS = {
|
|
1345
1361
|
maxBufferLength: 2,
|
|
@@ -1833,6 +1849,20 @@ function VideoSlotInner({
|
|
|
1833
1849
|
}
|
|
1834
1850
|
}, [mp4Src, isActive, isPrefetch, isPreloaded, isHlsSource]);
|
|
1835
1851
|
const isReady = isHlsSource ? hlsReady : mp4Ready;
|
|
1852
|
+
const [isVideoPlaying, setIsVideoPlaying] = react.useState(false);
|
|
1853
|
+
react.useEffect(() => {
|
|
1854
|
+
const video = videoRef.current;
|
|
1855
|
+
if (!video || !isActive) {
|
|
1856
|
+
setIsVideoPlaying(false);
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
const onPlaying = () => setIsVideoPlaying(true);
|
|
1860
|
+
video.addEventListener("playing", onPlaying);
|
|
1861
|
+
return () => {
|
|
1862
|
+
video.removeEventListener("playing", onPlaying);
|
|
1863
|
+
setIsVideoPlaying(false);
|
|
1864
|
+
};
|
|
1865
|
+
}, [isActive]);
|
|
1836
1866
|
const [hasPlayedAhead, setHasPlayedAhead] = react.useState(false);
|
|
1837
1867
|
react.useEffect(() => {
|
|
1838
1868
|
const video = videoRef.current;
|
|
@@ -1872,6 +1902,7 @@ function VideoSlotInner({
|
|
|
1872
1902
|
}, [isActive, isReady, hasPlayedAhead]);
|
|
1873
1903
|
react.useEffect(() => {
|
|
1874
1904
|
setHasPlayedAhead(false);
|
|
1905
|
+
setIsVideoPlaying(false);
|
|
1875
1906
|
}, [src]);
|
|
1876
1907
|
const wasActiveRef = react.useRef(false);
|
|
1877
1908
|
const [isManuallyPaused, setIsManuallyPaused] = react.useState(false);
|
|
@@ -1948,7 +1979,7 @@ function VideoSlotInner({
|
|
|
1948
1979
|
if (!video) return;
|
|
1949
1980
|
video.muted = isActive ? isMuted : true;
|
|
1950
1981
|
}, [isMuted, isActive]);
|
|
1951
|
-
const showPosterOverlay = !isReady && !hasPlayedAhead;
|
|
1982
|
+
const showPosterOverlay = isActive ? !isVideoPlaying : !isReady && !hasPlayedAhead;
|
|
1952
1983
|
const isPreDecoded = hasPlayedAhead;
|
|
1953
1984
|
const [showMuteIndicator, setShowMuteIndicator] = react.useState(false);
|
|
1954
1985
|
const muteIndicatorTimer = react.useRef(null);
|
|
@@ -2066,9 +2097,9 @@ function VideoSlotInner({
|
|
|
2066
2097
|
height: "100%",
|
|
2067
2098
|
objectFit: "cover",
|
|
2068
2099
|
// Hide video until ready to avoid black frame flash.
|
|
2069
|
-
// When pre-decoded, skip transition — first frame is already on canvas.
|
|
2100
|
+
// When pre-decoded or active, skip transition — first frame is already on canvas or playing.
|
|
2070
2101
|
opacity: showPosterOverlay ? 0 : 1,
|
|
2071
|
-
transition: isPreDecoded ? "none" : "opacity 0.15s ease"
|
|
2102
|
+
transition: isActive ? "none" : isPreDecoded ? "none" : "opacity 0.15s ease"
|
|
2072
2103
|
}
|
|
2073
2104
|
}
|
|
2074
2105
|
),
|
|
@@ -2082,7 +2113,7 @@ function VideoSlotInner({
|
|
|
2082
2113
|
backgroundSize: "cover",
|
|
2083
2114
|
backgroundPosition: "center",
|
|
2084
2115
|
opacity: showPosterOverlay ? 1 : 0,
|
|
2085
|
-
transition: "opacity 0.15s ease",
|
|
2116
|
+
transition: isActive ? "none" : "opacity 0.15s ease",
|
|
2086
2117
|
pointerEvents: "none"
|
|
2087
2118
|
}
|
|
2088
2119
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -503,6 +503,7 @@ declare class FeedManager {
|
|
|
503
503
|
constructor(dataSource: IDataSource, config?: FeedConfig, logger?: ILogger);
|
|
504
504
|
getDataSource(): IDataSource;
|
|
505
505
|
setDataSource(dataSource: IDataSource, reset?: boolean): void;
|
|
506
|
+
setInitialItems(items: ContentItem[]): void;
|
|
506
507
|
prefetch(ttlMs?: number): Promise<void>;
|
|
507
508
|
hasPrefetchCache(): boolean;
|
|
508
509
|
clearPrefetchCache(): void;
|
|
@@ -781,10 +782,12 @@ interface SDKContextValue {
|
|
|
781
782
|
interface ReelsProviderProps {
|
|
782
783
|
children: ReactNode;
|
|
783
784
|
adapters: SDKAdapters;
|
|
785
|
+
/** Seed initial items into feedManager */
|
|
786
|
+
initialItems?: ContentItem[];
|
|
784
787
|
/** Enable verbose logging (default: false) */
|
|
785
788
|
debug?: boolean;
|
|
786
789
|
}
|
|
787
|
-
declare function ReelsProvider({ children, adapters, debug }: ReelsProviderProps): react_jsx_runtime.JSX.Element;
|
|
790
|
+
declare function ReelsProvider({ children, adapters, initialItems, debug, }: ReelsProviderProps): react_jsx_runtime.JSX.Element;
|
|
788
791
|
declare function useSDK(): SDKContextValue;
|
|
789
792
|
|
|
790
793
|
declare function ReelsFeed({ renderOverlay, renderActions, renderPauseAction, renderLoading, renderEmpty, renderError: _renderError, showFps, loadMoreThreshold, onSlotChange, gestureConfig, snapConfig, initialMuted, onAutoplayBlocked, }: ReelsFeedProps): string | number | bigint | boolean | Iterable<react.ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -503,6 +503,7 @@ declare class FeedManager {
|
|
|
503
503
|
constructor(dataSource: IDataSource, config?: FeedConfig, logger?: ILogger);
|
|
504
504
|
getDataSource(): IDataSource;
|
|
505
505
|
setDataSource(dataSource: IDataSource, reset?: boolean): void;
|
|
506
|
+
setInitialItems(items: ContentItem[]): void;
|
|
506
507
|
prefetch(ttlMs?: number): Promise<void>;
|
|
507
508
|
hasPrefetchCache(): boolean;
|
|
508
509
|
clearPrefetchCache(): void;
|
|
@@ -781,10 +782,12 @@ interface SDKContextValue {
|
|
|
781
782
|
interface ReelsProviderProps {
|
|
782
783
|
children: ReactNode;
|
|
783
784
|
adapters: SDKAdapters;
|
|
785
|
+
/** Seed initial items into feedManager */
|
|
786
|
+
initialItems?: ContentItem[];
|
|
784
787
|
/** Enable verbose logging (default: false) */
|
|
785
788
|
debug?: boolean;
|
|
786
789
|
}
|
|
787
|
-
declare function ReelsProvider({ children, adapters, debug }: ReelsProviderProps): react_jsx_runtime.JSX.Element;
|
|
790
|
+
declare function ReelsProvider({ children, adapters, initialItems, debug, }: ReelsProviderProps): react_jsx_runtime.JSX.Element;
|
|
788
791
|
declare function useSDK(): SDKContextValue;
|
|
789
792
|
|
|
790
793
|
declare function ReelsFeed({ renderOverlay, renderActions, renderPauseAction, renderLoading, renderEmpty, renderError: _renderError, showFps, loadMoreThreshold, onSlotChange, gestureConfig, snapConfig, initialMuted, onAutoplayBlocked, }: ReelsFeedProps): string | number | bigint | boolean | Iterable<react.ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<react.ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null | undefined;
|
package/dist/index.js
CHANGED
|
@@ -438,6 +438,13 @@ var FeedManager = class {
|
|
|
438
438
|
// ═══════════════════════════════════════════
|
|
439
439
|
// PUBLIC API — Prefetch
|
|
440
440
|
// ═══════════════════════════════════════════
|
|
441
|
+
setInitialItems(items) {
|
|
442
|
+
this.prefetchCache = {
|
|
443
|
+
items,
|
|
444
|
+
nextCursor: null,
|
|
445
|
+
timestamp: Date.now()
|
|
446
|
+
};
|
|
447
|
+
}
|
|
441
448
|
async prefetch(ttlMs) {
|
|
442
449
|
if (this.prefetchCache) {
|
|
443
450
|
const ttl = ttlMs ?? this.config.staleTTL;
|
|
@@ -1131,7 +1138,12 @@ function useSnapAnimation(config = {}) {
|
|
|
1131
1138
|
return { animateSnap, animateBounceBack, cancelAnimation };
|
|
1132
1139
|
}
|
|
1133
1140
|
var SDKContext = createContext(null);
|
|
1134
|
-
function ReelsProvider({
|
|
1141
|
+
function ReelsProvider({
|
|
1142
|
+
children,
|
|
1143
|
+
adapters,
|
|
1144
|
+
initialItems,
|
|
1145
|
+
debug = false
|
|
1146
|
+
}) {
|
|
1135
1147
|
const logger = adapters.logger;
|
|
1136
1148
|
const sdkRef = useRef(null);
|
|
1137
1149
|
const value = useMemo(() => {
|
|
@@ -1142,6 +1154,9 @@ function ReelsProvider({ children, adapters, debug = false }) {
|
|
|
1142
1154
|
sdkRef.current.optimisticManager.destroy();
|
|
1143
1155
|
}
|
|
1144
1156
|
const feedManager = new FeedManager(adapters.dataSource, {}, logger);
|
|
1157
|
+
if (initialItems && initialItems.length > 0) {
|
|
1158
|
+
feedManager.setInitialItems(initialItems);
|
|
1159
|
+
}
|
|
1145
1160
|
const playerEngine = new PlayerEngine(
|
|
1146
1161
|
{},
|
|
1147
1162
|
adapters.analytics,
|
|
@@ -1330,10 +1345,11 @@ var ACTIVE_HLS_DEFAULTS = {
|
|
|
1330
1345
|
maxMaxBufferLength: 15,
|
|
1331
1346
|
capLevelToPlayerSize: true,
|
|
1332
1347
|
startLevel: 0,
|
|
1333
|
-
abrEwmaDefaultEstimate:
|
|
1348
|
+
abrEwmaDefaultEstimate: 2e6,
|
|
1334
1349
|
lowLatencyMode: false,
|
|
1335
1350
|
backBufferLength: 5,
|
|
1336
|
-
enableWorker: true
|
|
1351
|
+
enableWorker: true,
|
|
1352
|
+
startFragPrefetch: true
|
|
1337
1353
|
};
|
|
1338
1354
|
var HOT_HLS_DEFAULTS = {
|
|
1339
1355
|
maxBufferLength: 2,
|
|
@@ -1827,6 +1843,20 @@ function VideoSlotInner({
|
|
|
1827
1843
|
}
|
|
1828
1844
|
}, [mp4Src, isActive, isPrefetch, isPreloaded, isHlsSource]);
|
|
1829
1845
|
const isReady = isHlsSource ? hlsReady : mp4Ready;
|
|
1846
|
+
const [isVideoPlaying, setIsVideoPlaying] = useState(false);
|
|
1847
|
+
useEffect(() => {
|
|
1848
|
+
const video = videoRef.current;
|
|
1849
|
+
if (!video || !isActive) {
|
|
1850
|
+
setIsVideoPlaying(false);
|
|
1851
|
+
return;
|
|
1852
|
+
}
|
|
1853
|
+
const onPlaying = () => setIsVideoPlaying(true);
|
|
1854
|
+
video.addEventListener("playing", onPlaying);
|
|
1855
|
+
return () => {
|
|
1856
|
+
video.removeEventListener("playing", onPlaying);
|
|
1857
|
+
setIsVideoPlaying(false);
|
|
1858
|
+
};
|
|
1859
|
+
}, [isActive]);
|
|
1830
1860
|
const [hasPlayedAhead, setHasPlayedAhead] = useState(false);
|
|
1831
1861
|
useEffect(() => {
|
|
1832
1862
|
const video = videoRef.current;
|
|
@@ -1866,6 +1896,7 @@ function VideoSlotInner({
|
|
|
1866
1896
|
}, [isActive, isReady, hasPlayedAhead]);
|
|
1867
1897
|
useEffect(() => {
|
|
1868
1898
|
setHasPlayedAhead(false);
|
|
1899
|
+
setIsVideoPlaying(false);
|
|
1869
1900
|
}, [src]);
|
|
1870
1901
|
const wasActiveRef = useRef(false);
|
|
1871
1902
|
const [isManuallyPaused, setIsManuallyPaused] = useState(false);
|
|
@@ -1942,7 +1973,7 @@ function VideoSlotInner({
|
|
|
1942
1973
|
if (!video) return;
|
|
1943
1974
|
video.muted = isActive ? isMuted : true;
|
|
1944
1975
|
}, [isMuted, isActive]);
|
|
1945
|
-
const showPosterOverlay = !isReady && !hasPlayedAhead;
|
|
1976
|
+
const showPosterOverlay = isActive ? !isVideoPlaying : !isReady && !hasPlayedAhead;
|
|
1946
1977
|
const isPreDecoded = hasPlayedAhead;
|
|
1947
1978
|
const [showMuteIndicator, setShowMuteIndicator] = useState(false);
|
|
1948
1979
|
const muteIndicatorTimer = useRef(null);
|
|
@@ -2060,9 +2091,9 @@ function VideoSlotInner({
|
|
|
2060
2091
|
height: "100%",
|
|
2061
2092
|
objectFit: "cover",
|
|
2062
2093
|
// Hide video until ready to avoid black frame flash.
|
|
2063
|
-
// When pre-decoded, skip transition — first frame is already on canvas.
|
|
2094
|
+
// When pre-decoded or active, skip transition — first frame is already on canvas or playing.
|
|
2064
2095
|
opacity: showPosterOverlay ? 0 : 1,
|
|
2065
|
-
transition: isPreDecoded ? "none" : "opacity 0.15s ease"
|
|
2096
|
+
transition: isActive ? "none" : isPreDecoded ? "none" : "opacity 0.15s ease"
|
|
2066
2097
|
}
|
|
2067
2098
|
}
|
|
2068
2099
|
),
|
|
@@ -2076,7 +2107,7 @@ function VideoSlotInner({
|
|
|
2076
2107
|
backgroundSize: "cover",
|
|
2077
2108
|
backgroundPosition: "center",
|
|
2078
2109
|
opacity: showPosterOverlay ? 1 : 0,
|
|
2079
|
-
transition: "opacity 0.15s ease",
|
|
2110
|
+
transition: isActive ? "none" : "opacity 0.15s ease",
|
|
2080
2111
|
pointerEvents: "none"
|
|
2081
2112
|
}
|
|
2082
2113
|
}
|