@xhub-short/sdk 0.1.0-beta.3 → 0.1.0-beta.5
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 +69 -0
- package/dist/index.d.ts +240 -8
- package/dist/index.js +118 -6
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -597,6 +597,75 @@ import { VideoSlotOverlay, VideoSlotPoster } from '@xhub-short/ui';
|
|
|
597
597
|
|
|
598
598
|
---
|
|
599
599
|
|
|
600
|
+
## 👤 Guest Mode (Chế độ khách)
|
|
601
|
+
|
|
602
|
+
SDK hỗ trợ chế độ khách cho phép người dùng chưa đăng nhập xem video và bình luận (read-only). Các tương tác (Like, Comment, Follow) sẽ bị chặn và trigger callback để Host App xử lý (ví dụ: hiện modal đăng nhập).
|
|
603
|
+
|
|
604
|
+
### Cấu hình
|
|
605
|
+
|
|
606
|
+
```tsx
|
|
607
|
+
<ShortVideoRoot
|
|
608
|
+
config={{
|
|
609
|
+
// ...
|
|
610
|
+
guest: {
|
|
611
|
+
/**
|
|
612
|
+
* 'auto': Tự động detect dựa trên auth token (default)
|
|
613
|
+
* true: Force guest mode
|
|
614
|
+
* false: Disable guest mode
|
|
615
|
+
*/
|
|
616
|
+
mode: 'auto',
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Callback khi guest thực hiện hành động cần auth (Like, Comment, Follow...)
|
|
620
|
+
*/
|
|
621
|
+
onAction: (action, context) => {
|
|
622
|
+
console.log('Guest Action:', action, context);
|
|
623
|
+
// VD: showLoginModal();
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}}
|
|
627
|
+
>
|
|
628
|
+
<VideoFeed />
|
|
629
|
+
</ShortVideoRoot>
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### Các hành động được chặn
|
|
633
|
+
- **Like / Bookmark**: Trigger `onAction`
|
|
634
|
+
- **Follow**: Trigger `onAction`
|
|
635
|
+
- **Comment Input**: Hiển thị nút "Login to comment". Khi click triggers `onAction` (`action='comment'`).
|
|
636
|
+
|
|
637
|
+
---
|
|
638
|
+
|
|
639
|
+
## ⚡ Prefetch Data (Tải trước dữ liệu)
|
|
640
|
+
|
|
641
|
+
Cho phép Host App tải trước dữ liệu Feed (Reels) để trải nghiệm hiển thị tức thì (instant loading).
|
|
642
|
+
|
|
643
|
+
### Cách sử dụng
|
|
644
|
+
|
|
645
|
+
Gọi hàm `prefetchFeed` trước khi mount SDK components (ví dụ: khi hover vào menu Reels hoặc trong route loader).
|
|
646
|
+
|
|
647
|
+
```tsx
|
|
648
|
+
import { prefetchFeed } from '@xhub-short/sdk';
|
|
649
|
+
|
|
650
|
+
// 1. Prefetch data (lưu vào bộ nhớ tạm)
|
|
651
|
+
// Có thể gọi ở bất kỳ đâu trong Host App
|
|
652
|
+
await prefetchFeed(sdkConfig, { ttl: 5 * 60 * 1000 });
|
|
653
|
+
|
|
654
|
+
// ... Sau đó ...
|
|
655
|
+
|
|
656
|
+
// 2. Khi User vào trang Reels, SDK sẽ tự động dùng data đã fetch
|
|
657
|
+
<ShortVideoRoot config={sdkConfig}>
|
|
658
|
+
<VideoFeed />
|
|
659
|
+
</ShortVideoRoot>
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
### Đặc điểm
|
|
663
|
+
- **In-Memory Cache**: Dữ liệu chỉ lưu tạm trong RAM, mất khi refresh trang (đảm bảo fresh data).
|
|
664
|
+
- **Auto-Consume**: `ShortVideoRoot` tự động tiêu thụ cache và xóa sau khi dùng.
|
|
665
|
+
- **Performance**: Giúp giảm thời gian chờ đợi (LCP) xuống gần bằng 0 khi user chuyển trang.
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
600
669
|
## 🔗 Liên kết với các Packages
|
|
601
670
|
|
|
602
671
|
| Package | Quan hệ với SDK |
|
package/dist/index.d.ts
CHANGED
|
@@ -379,6 +379,7 @@ declare function TranslatedSheetHeader(props: SheetHeaderProps): ReactElement;
|
|
|
379
379
|
declare function TranslatedCommentList(props: CommentListProps): ReactElement;
|
|
380
380
|
/**
|
|
381
381
|
* Translated CommentInput - auto-injects i18n strings
|
|
382
|
+
* Handles guest mode by showing login prompt
|
|
382
383
|
*/
|
|
383
384
|
declare function TranslatedCommentInput(props: CommentInputProps): ReactElement;
|
|
384
385
|
declare const CommentSheet: typeof CommentSheetInner & {
|
|
@@ -1272,6 +1273,67 @@ interface AdaptersConfig {
|
|
|
1272
1273
|
/** Poster loader adapter for preloading thumbnails */
|
|
1273
1274
|
posterLoader?: IPosterLoader;
|
|
1274
1275
|
}
|
|
1276
|
+
/**
|
|
1277
|
+
* Actions that require authentication
|
|
1278
|
+
*
|
|
1279
|
+
* These actions will trigger the `onAction` callback in guest mode
|
|
1280
|
+
* instead of making API requests.
|
|
1281
|
+
*/
|
|
1282
|
+
type GuestAction = 'like' | 'unlike' | 'comment' | 'reply' | 'follow' | 'unfollow' | 'bookmark' | 'like_comment';
|
|
1283
|
+
/**
|
|
1284
|
+
* Context for guest action
|
|
1285
|
+
*
|
|
1286
|
+
* Provides information about the resource being acted upon.
|
|
1287
|
+
*/
|
|
1288
|
+
interface GuestActionContext {
|
|
1289
|
+
/** Type of resource */
|
|
1290
|
+
resourceType: 'video' | 'comment' | 'author';
|
|
1291
|
+
/** Resource ID */
|
|
1292
|
+
resourceId: string;
|
|
1293
|
+
/** Additional metadata (e.g., videoId for comment, authorId for follow) */
|
|
1294
|
+
metadata?: Record<string, unknown>;
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Guest mode configuration
|
|
1298
|
+
*
|
|
1299
|
+
* Controls how the SDK behaves for unauthenticated users.
|
|
1300
|
+
*/
|
|
1301
|
+
interface GuestModeConfig {
|
|
1302
|
+
/**
|
|
1303
|
+
* Enable guest mode
|
|
1304
|
+
*
|
|
1305
|
+
* - 'auto': Automatically detect based on getAccessToken() returning null (default)
|
|
1306
|
+
* - true: Force guest mode (always treat user as guest)
|
|
1307
|
+
* - false: Disable guest mode (require authentication)
|
|
1308
|
+
*
|
|
1309
|
+
* @default 'auto'
|
|
1310
|
+
*/
|
|
1311
|
+
mode?: 'auto' | boolean;
|
|
1312
|
+
/**
|
|
1313
|
+
* Callback when guest tries to perform authenticated action
|
|
1314
|
+
*
|
|
1315
|
+
* Called instead of making API requests when user is in guest mode.
|
|
1316
|
+
* Host app can use this to show login modal, redirect, etc.
|
|
1317
|
+
*
|
|
1318
|
+
* @param action - The action guest tried to perform
|
|
1319
|
+
* @param context - Context about the resource
|
|
1320
|
+
*
|
|
1321
|
+
* @example
|
|
1322
|
+
* ```tsx
|
|
1323
|
+
* <ShortVideoProvider config={{
|
|
1324
|
+
* guest: {
|
|
1325
|
+
* onAction: (action, context) => {
|
|
1326
|
+
* console.log(`Guest tried to ${action}`, context);
|
|
1327
|
+
* if (action === 'like' || action === 'comment') {
|
|
1328
|
+
* showLoginModal();
|
|
1329
|
+
* }
|
|
1330
|
+
* }
|
|
1331
|
+
* }
|
|
1332
|
+
* }}>
|
|
1333
|
+
* ```
|
|
1334
|
+
*/
|
|
1335
|
+
onAction?: (action: GuestAction, context: GuestActionContext) => void;
|
|
1336
|
+
}
|
|
1275
1337
|
/**
|
|
1276
1338
|
* SDK Configuration
|
|
1277
1339
|
*
|
|
@@ -1419,6 +1481,30 @@ interface SDKConfig {
|
|
|
1419
1481
|
* @default false
|
|
1420
1482
|
*/
|
|
1421
1483
|
debug?: boolean;
|
|
1484
|
+
/**
|
|
1485
|
+
* Guest mode configuration
|
|
1486
|
+
*
|
|
1487
|
+
* When enabled, SDK allows unauthenticated users to browse content.
|
|
1488
|
+
* Interactive actions (like, comment, follow) will trigger callbacks
|
|
1489
|
+
* instead of making API requests.
|
|
1490
|
+
*
|
|
1491
|
+
* @example
|
|
1492
|
+
* ```tsx
|
|
1493
|
+
* <ShortVideoProvider config={{
|
|
1494
|
+
* guest: {
|
|
1495
|
+
* mode: 'auto',
|
|
1496
|
+
* onAction: (action, context) => {
|
|
1497
|
+
* if (action === 'like' || action === 'comment') {
|
|
1498
|
+
* showLoginModal();
|
|
1499
|
+
* }
|
|
1500
|
+
* }
|
|
1501
|
+
* }
|
|
1502
|
+
* }}>
|
|
1503
|
+
* <App />
|
|
1504
|
+
* </ShortVideoProvider>
|
|
1505
|
+
* ```
|
|
1506
|
+
*/
|
|
1507
|
+
guest?: GuestModeConfig;
|
|
1422
1508
|
}
|
|
1423
1509
|
/**
|
|
1424
1510
|
* Props for ShortVideoProvider component
|
|
@@ -1861,6 +1947,75 @@ interface UsePlayerReturn {
|
|
|
1861
1947
|
* ```
|
|
1862
1948
|
*/
|
|
1863
1949
|
declare function usePlayer(): UsePlayerReturn;
|
|
1950
|
+
/**
|
|
1951
|
+
* Return type for usePlayerCore hook
|
|
1952
|
+
*
|
|
1953
|
+
* This is a subset of UsePlayerReturn that excludes time-based fields
|
|
1954
|
+
* (currentTime, duration, buffered, watchTime, loopCount, progress, bufferProgress)
|
|
1955
|
+
* to prevent re-renders during playback.
|
|
1956
|
+
*/
|
|
1957
|
+
interface UsePlayerCoreReturn {
|
|
1958
|
+
/** Currently loaded video */
|
|
1959
|
+
currentVideo: VideoItem | null;
|
|
1960
|
+
/** Player status */
|
|
1961
|
+
status: PlayerStatus;
|
|
1962
|
+
/** Whether audio is muted */
|
|
1963
|
+
muted: boolean;
|
|
1964
|
+
/** Volume level (0-1) */
|
|
1965
|
+
volume: number;
|
|
1966
|
+
/** Current error, if any */
|
|
1967
|
+
error: PlayerError | null;
|
|
1968
|
+
/** Playback speed rate */
|
|
1969
|
+
playbackRate: number;
|
|
1970
|
+
/** Whether video has ended */
|
|
1971
|
+
ended: boolean;
|
|
1972
|
+
/** Whether currently playing */
|
|
1973
|
+
isPlaying: boolean;
|
|
1974
|
+
/** Whether currently paused */
|
|
1975
|
+
isPaused: boolean;
|
|
1976
|
+
/** Whether currently buffering */
|
|
1977
|
+
isBuffering: boolean;
|
|
1978
|
+
/** Whether currently loading */
|
|
1979
|
+
isLoading: boolean;
|
|
1980
|
+
/** Whether in error state */
|
|
1981
|
+
hasError: boolean;
|
|
1982
|
+
/** Whether in idle state */
|
|
1983
|
+
isIdle: boolean;
|
|
1984
|
+
/** Load a video */
|
|
1985
|
+
load: (video: VideoItem) => void;
|
|
1986
|
+
/** Start playback */
|
|
1987
|
+
play: () => boolean;
|
|
1988
|
+
/** Pause playback */
|
|
1989
|
+
pause: () => boolean;
|
|
1990
|
+
/** Toggle play/pause */
|
|
1991
|
+
togglePlay: () => boolean;
|
|
1992
|
+
/** Seek to position */
|
|
1993
|
+
seek: (time: number) => boolean;
|
|
1994
|
+
/** Set muted state */
|
|
1995
|
+
setMuted: (muted: boolean) => void;
|
|
1996
|
+
/** Toggle mute */
|
|
1997
|
+
toggleMute: () => void;
|
|
1998
|
+
/** Set volume (0-1) */
|
|
1999
|
+
setVolume: (volume: number) => void;
|
|
2000
|
+
/** Set playback rate */
|
|
2001
|
+
setPlaybackRate: (rate: number) => void;
|
|
2002
|
+
/** Report time update */
|
|
2003
|
+
onTimeUpdate: (time: number) => void;
|
|
2004
|
+
/** Report buffering started */
|
|
2005
|
+
onBuffering: () => boolean;
|
|
2006
|
+
/** Report buffering ended */
|
|
2007
|
+
onBufferingEnd: () => boolean;
|
|
2008
|
+
/** Report buffer progress */
|
|
2009
|
+
onBufferProgress: (percent: number) => void;
|
|
2010
|
+
/** Report video ended */
|
|
2011
|
+
onEnded: () => void;
|
|
2012
|
+
/** Report error */
|
|
2013
|
+
onError: (error: Error, mediaError?: MediaError) => void;
|
|
2014
|
+
/** Reset player */
|
|
2015
|
+
reset: () => void;
|
|
2016
|
+
/** Pre-built event handlers for <video> element */
|
|
2017
|
+
handlers: VideoElementHandlers;
|
|
2018
|
+
}
|
|
1864
2019
|
/**
|
|
1865
2020
|
* Return type for usePlayerForVideo hook
|
|
1866
2021
|
*/
|
|
@@ -2082,13 +2237,6 @@ declare function useOptimistic(): {
|
|
|
2082
2237
|
};
|
|
2083
2238
|
type UseOptimisticReturn = ReturnType<typeof useOptimistic>;
|
|
2084
2239
|
|
|
2085
|
-
/**
|
|
2086
|
-
* SDK Factory and Store Management
|
|
2087
|
-
*
|
|
2088
|
-
* Creates and manages Core Domain managers with Dependency Injection.
|
|
2089
|
-
* Supports configurable adapters and manager options.
|
|
2090
|
-
*/
|
|
2091
|
-
|
|
2092
2240
|
/**
|
|
2093
2241
|
* SDK instance containing all managers
|
|
2094
2242
|
*/
|
|
@@ -2116,6 +2264,13 @@ interface SDKInstance {
|
|
|
2116
2264
|
/** Comment adapter (optional - only if comment feature is enabled) */
|
|
2117
2265
|
comment?: ICommentAdapter;
|
|
2118
2266
|
};
|
|
2267
|
+
/** Guest mode configuration */
|
|
2268
|
+
guest: {
|
|
2269
|
+
/** Whether user is currently in guest mode */
|
|
2270
|
+
isGuest: boolean;
|
|
2271
|
+
/** Guest mode config from SDKConfig */
|
|
2272
|
+
config?: GuestModeConfig;
|
|
2273
|
+
};
|
|
2119
2274
|
/** Destroy all managers and cleanup resources */
|
|
2120
2275
|
destroy: () => void;
|
|
2121
2276
|
}
|
|
@@ -2151,6 +2306,22 @@ declare function getSDK(config?: SDKConfig): SDKInstance;
|
|
|
2151
2306
|
* or when cleaning up (e.g., in tests).
|
|
2152
2307
|
*/
|
|
2153
2308
|
declare function destroySDK(): void;
|
|
2309
|
+
/**
|
|
2310
|
+
* Prefetch feed data (Standalone functionality)
|
|
2311
|
+
*
|
|
2312
|
+
* Allows host app to fetch data before mounting the SDK components.
|
|
2313
|
+
* Data is stored in static in-memory cache and automatically consumed
|
|
2314
|
+
* when SDK initializes with the same configuration.
|
|
2315
|
+
*
|
|
2316
|
+
* @example
|
|
2317
|
+
* ```ts
|
|
2318
|
+
* // In routing logic or hover handler
|
|
2319
|
+
* await prefetchFeed(config);
|
|
2320
|
+
* ```
|
|
2321
|
+
*/
|
|
2322
|
+
declare function prefetchFeed(config: SDKConfig, options?: {
|
|
2323
|
+
ttl?: number;
|
|
2324
|
+
}): Promise<void>;
|
|
2154
2325
|
|
|
2155
2326
|
declare function useSDK(): SDKInstance;
|
|
2156
2327
|
|
|
@@ -2520,4 +2691,65 @@ declare function getMessages(locale: string): MessageCatalog;
|
|
|
2520
2691
|
*/
|
|
2521
2692
|
declare function isLocaleSupported(locale: string): locale is SupportedLocale;
|
|
2522
2693
|
|
|
2523
|
-
|
|
2694
|
+
/**
|
|
2695
|
+
* useGuestMode Hook
|
|
2696
|
+
*
|
|
2697
|
+
* Detects and manages guest mode state.
|
|
2698
|
+
* Provides utilities for handling guest actions.
|
|
2699
|
+
*/
|
|
2700
|
+
|
|
2701
|
+
/**
|
|
2702
|
+
* Return type for useGuestMode hook
|
|
2703
|
+
*/
|
|
2704
|
+
interface UseGuestModeReturn {
|
|
2705
|
+
/**
|
|
2706
|
+
* Whether the current user is in guest mode
|
|
2707
|
+
*/
|
|
2708
|
+
isGuest: boolean;
|
|
2709
|
+
/**
|
|
2710
|
+
* Trigger a guest action
|
|
2711
|
+
*
|
|
2712
|
+
* If in guest mode, calls the onAction callback.
|
|
2713
|
+
* If authenticated, returns false (action should proceed normally).
|
|
2714
|
+
*
|
|
2715
|
+
* @param action - The action being attempted
|
|
2716
|
+
* @param context - Context about the resource
|
|
2717
|
+
* @returns true if action was handled (guest mode), false if should proceed (authenticated)
|
|
2718
|
+
*/
|
|
2719
|
+
handleGuestAction: (action: GuestAction, context: GuestActionContext) => boolean;
|
|
2720
|
+
/**
|
|
2721
|
+
* Check if user is authenticated
|
|
2722
|
+
*/
|
|
2723
|
+
isAuthenticated: boolean;
|
|
2724
|
+
}
|
|
2725
|
+
/**
|
|
2726
|
+
* Hook for guest mode detection and handling
|
|
2727
|
+
*
|
|
2728
|
+
* Automatically detects guest mode based on:
|
|
2729
|
+
* 1. config.guest.mode setting
|
|
2730
|
+
* 2. Whether accessToken is available (auto-detection)
|
|
2731
|
+
*
|
|
2732
|
+
* @param guestConfig - Guest mode configuration from SDK config
|
|
2733
|
+
* @returns Guest mode state and utilities
|
|
2734
|
+
*
|
|
2735
|
+
* @example
|
|
2736
|
+
* ```tsx
|
|
2737
|
+
* function ActionBar() {
|
|
2738
|
+
* const { isGuest, handleGuestAction } = useGuestMode(config?.guest);
|
|
2739
|
+
*
|
|
2740
|
+
* const handleLike = () => {
|
|
2741
|
+
* if (handleGuestAction('like', {
|
|
2742
|
+
* resourceType: 'video',
|
|
2743
|
+
* resourceId: video.id
|
|
2744
|
+
* })) {
|
|
2745
|
+
* return; // Guest action handled
|
|
2746
|
+
* }
|
|
2747
|
+
* // Proceed with normal like
|
|
2748
|
+
* toggleLike(video.id);
|
|
2749
|
+
* };
|
|
2750
|
+
* }
|
|
2751
|
+
* ```
|
|
2752
|
+
*/
|
|
2753
|
+
declare function useGuestMode(guestConfigOverride?: GuestModeConfig): UseGuestModeReturn;
|
|
2754
|
+
|
|
2755
|
+
export { ActionBar, type ActionBarIconSet, type ActionBarProps as ActionBarWiredProps, type AdaptersConfig, AuthorInfo, type AuthorInfoProps as AuthorInfoWiredProps, CommentSheet, type CommentSheetProps, DEFAULT_LOCALE, DefaultSlot, type DefaultSlotProps, type GuestAction, type GuestActionContext, type GuestModeConfig, type HookReturn, LocalizationAdapter, LocalizationContext, LocalizationProvider, type LocalizationProviderProps, ProgressBar, type ProgressBarProps, type SDKConfig, type SDKInstance, SDKPlayerError, SUPPORTED_LOCALES, ShortVideoProvider, type ShortVideoProviderProps, ShortVideoRoot, type ShortVideoRootProps, type SupportedLocale, type SwipeConfig, type SwipeDirection, type SwipeState, type TranslateFn, type UseCommentOptions, type UseCommentReturn, type UseFeedReturn, type UseGuestModeReturn, type UseLifecycleOptions, type UseLifecycleReturn, type UseOptimisticReturn, type UsePlayerCoreReturn, type UsePlayerForVideoReturn, type UsePlayerReturn, type UseResourceAllocationReturn, type UseResourceReturn, type UseSwipeGestureReturn, type UseTranslationReturn, type VideoElementHandlers, VideoFeed, type VideoFeedProps, VideoInfo, type VideoInfoWiredProps, VideoPlayer, type VideoPlayerProps, VideoSlot, type VideoSlotWiredProps, type WireConfig, createSDK, createSimpleWireConfig, createWiredComponent, destroySDK, enMessages, getMessages, getSDK, isLocaleSupported, messageCatalogs, parseMessage, prefetchFeed, resetCommentManager, useComment, useFeed, useFeedSelector, useGuestMode, useLifecycle, useLifecycleSelector, useLocalization, useOptimistic, useOptimisticSelector, useOptionalLocalization, useOptionalTranslation, usePlayer, usePlayerForVideo, usePlayerSelector, useResource, useResourceAllocation, useResourceSelector, useSDK, useSwipeGesture, useTranslation, viMessages };
|
package/dist/index.js
CHANGED
|
@@ -117,6 +117,35 @@ function useFeed() {
|
|
|
117
117
|
reset
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
|
+
function useGuestMode(guestConfigOverride) {
|
|
121
|
+
const sdk = useSDK();
|
|
122
|
+
const config = guestConfigOverride ?? sdk.guest.config;
|
|
123
|
+
const isGuest = useMemo(() => {
|
|
124
|
+
if (guestConfigOverride?.mode !== void 0) {
|
|
125
|
+
if (guestConfigOverride.mode === true) return true;
|
|
126
|
+
if (guestConfigOverride.mode === false) return false;
|
|
127
|
+
}
|
|
128
|
+
return sdk.guest.isGuest;
|
|
129
|
+
}, [guestConfigOverride?.mode, sdk.guest.isGuest]);
|
|
130
|
+
const isAuthenticated = !isGuest;
|
|
131
|
+
const handleGuestAction = useCallback(
|
|
132
|
+
(action, context) => {
|
|
133
|
+
if (!isGuest) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
if (config?.onAction) {
|
|
137
|
+
config.onAction(action, context);
|
|
138
|
+
}
|
|
139
|
+
return true;
|
|
140
|
+
},
|
|
141
|
+
[isGuest, config]
|
|
142
|
+
);
|
|
143
|
+
return {
|
|
144
|
+
isGuest,
|
|
145
|
+
isAuthenticated,
|
|
146
|
+
handleGuestAction
|
|
147
|
+
};
|
|
148
|
+
}
|
|
120
149
|
function useOptimisticSelector(selector) {
|
|
121
150
|
const { optimisticManager } = useSDK();
|
|
122
151
|
return useSyncExternalStore(
|
|
@@ -246,11 +275,18 @@ function ActionBar({
|
|
|
246
275
|
isLikePending
|
|
247
276
|
};
|
|
248
277
|
}, [overrideState, currentVideo, isLikePending]);
|
|
278
|
+
const { handleGuestAction } = useGuestMode();
|
|
249
279
|
const handleToggleLike = useCallback(() => {
|
|
280
|
+
if (handleGuestAction("like", {
|
|
281
|
+
resourceType: "video",
|
|
282
|
+
resourceId: video.id
|
|
283
|
+
})) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
250
286
|
const wasLiked = currentVideo.isLiked;
|
|
251
287
|
toggleLike(video.id);
|
|
252
288
|
onLikeToggle?.(!wasLiked, video.id);
|
|
253
|
-
}, [currentVideo.isLiked, video.id, toggleLike, onLikeToggle]);
|
|
289
|
+
}, [currentVideo.isLiked, video.id, toggleLike, onLikeToggle, handleGuestAction]);
|
|
254
290
|
const handleOpenComments = useCallback(() => {
|
|
255
291
|
onOpenComments?.(video.id);
|
|
256
292
|
}, [onOpenComments, video.id]);
|
|
@@ -266,8 +302,14 @@ function ActionBar({
|
|
|
266
302
|
[handleToggleLike, handleOpenComments, handleShare]
|
|
267
303
|
);
|
|
268
304
|
const handleBookmarkToggle = useCallback(() => {
|
|
305
|
+
if (handleGuestAction("bookmark", {
|
|
306
|
+
resourceType: "video",
|
|
307
|
+
resourceId: video.id
|
|
308
|
+
})) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
269
311
|
onBookmarkToggle?.(!isBookmarked, video.id);
|
|
270
|
-
}, [onBookmarkToggle, isBookmarked, video.id]);
|
|
312
|
+
}, [onBookmarkToggle, isBookmarked, video.id, handleGuestAction]);
|
|
271
313
|
return /* @__PURE__ */ jsxs(
|
|
272
314
|
ActionBarHeadless,
|
|
273
315
|
{
|
|
@@ -388,7 +430,11 @@ var enMessages = {
|
|
|
388
430
|
"aria.addMedia": "Add media",
|
|
389
431
|
"aria.submitComment": "Submit comment",
|
|
390
432
|
"aria.openEmoji": "Open emoji",
|
|
391
|
-
"aria.cancelReply": "Cancel reply"
|
|
433
|
+
"aria.cancelReply": "Cancel reply",
|
|
434
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
435
|
+
// Guest Mode
|
|
436
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
437
|
+
"guest.loginToComment": "Log in to comment"
|
|
392
438
|
};
|
|
393
439
|
|
|
394
440
|
// src/localization/messages/vi.ts
|
|
@@ -482,7 +528,11 @@ var viMessages = {
|
|
|
482
528
|
"aria.addMedia": "Th\xEAm \u1EA3nh",
|
|
483
529
|
"aria.submitComment": "G\u1EEDi b\xECnh lu\u1EADn",
|
|
484
530
|
"aria.openEmoji": "M\u1EDF emoji",
|
|
485
|
-
"aria.cancelReply": "H\u1EE7y tr\u1EA3 l\u1EDDi"
|
|
531
|
+
"aria.cancelReply": "H\u1EE7y tr\u1EA3 l\u1EDDi",
|
|
532
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
533
|
+
// Guest Mode
|
|
534
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
535
|
+
"guest.loginToComment": "\u0110\u0103ng nh\u1EADp \u0111\u1EC3 b\xECnh lu\u1EADn"
|
|
486
536
|
};
|
|
487
537
|
|
|
488
538
|
// src/localization/messages/index.ts
|
|
@@ -795,7 +845,15 @@ function AuthorInfoRoot({
|
|
|
795
845
|
isFollowPending
|
|
796
846
|
};
|
|
797
847
|
}, [overrideState, currentVideo.author, currentVideo.isFollowing, isFollowPending]);
|
|
848
|
+
const { handleGuestAction } = useGuestMode();
|
|
798
849
|
const handleToggleFollow = useCallback(async () => {
|
|
850
|
+
if (handleGuestAction("follow", {
|
|
851
|
+
resourceType: "author",
|
|
852
|
+
resourceId: currentVideo.author.id,
|
|
853
|
+
metadata: { authorId: currentVideo.author.id }
|
|
854
|
+
})) {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
799
857
|
const wasFollowing = currentVideo.isFollowing;
|
|
800
858
|
try {
|
|
801
859
|
const success = await toggleFollow(video.id);
|
|
@@ -804,7 +862,14 @@ function AuthorInfoRoot({
|
|
|
804
862
|
}
|
|
805
863
|
} catch {
|
|
806
864
|
}
|
|
807
|
-
}, [
|
|
865
|
+
}, [
|
|
866
|
+
currentVideo.isFollowing,
|
|
867
|
+
currentVideo.author.id,
|
|
868
|
+
video.id,
|
|
869
|
+
toggleFollow,
|
|
870
|
+
onFollowToggle,
|
|
871
|
+
handleGuestAction
|
|
872
|
+
]);
|
|
808
873
|
const handleOpenProfile = useCallback(() => {
|
|
809
874
|
onOpenProfile?.(currentVideo.author);
|
|
810
875
|
}, [onOpenProfile, currentVideo.author]);
|
|
@@ -1148,6 +1213,44 @@ function TranslatedCommentList(props) {
|
|
|
1148
1213
|
}
|
|
1149
1214
|
function TranslatedCommentInput(props) {
|
|
1150
1215
|
const i18n = useOptionalTranslation();
|
|
1216
|
+
const { isGuest, handleGuestAction } = useGuestMode();
|
|
1217
|
+
const handleGuestClick = useCallback(() => {
|
|
1218
|
+
handleGuestAction("comment", {
|
|
1219
|
+
resourceType: "comment",
|
|
1220
|
+
resourceId: "guest-intent"
|
|
1221
|
+
// Fallback ID since we don't have videoId here
|
|
1222
|
+
});
|
|
1223
|
+
}, [handleGuestAction]);
|
|
1224
|
+
if (isGuest) {
|
|
1225
|
+
return /* @__PURE__ */ jsx(
|
|
1226
|
+
"div",
|
|
1227
|
+
{
|
|
1228
|
+
className: "sv-comment-input-guest",
|
|
1229
|
+
onClick: handleGuestClick,
|
|
1230
|
+
onKeyDown: (e) => {
|
|
1231
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1232
|
+
handleGuestClick();
|
|
1233
|
+
}
|
|
1234
|
+
},
|
|
1235
|
+
role: "button",
|
|
1236
|
+
tabIndex: 0,
|
|
1237
|
+
style: {
|
|
1238
|
+
padding: "16px",
|
|
1239
|
+
borderTop: "1px solid rgba(0,0,0,0.1)",
|
|
1240
|
+
display: "flex",
|
|
1241
|
+
alignItems: "center",
|
|
1242
|
+
justifyContent: "center",
|
|
1243
|
+
cursor: "pointer",
|
|
1244
|
+
background: "var(--sv-bg-surface, #fff)",
|
|
1245
|
+
color: "var(--sv-color-primary, #fe2c55)",
|
|
1246
|
+
fontWeight: 600,
|
|
1247
|
+
fontSize: "14px",
|
|
1248
|
+
width: "100%"
|
|
1249
|
+
},
|
|
1250
|
+
children: i18n?.t("guest.loginToComment") ?? "Log in to comment"
|
|
1251
|
+
}
|
|
1252
|
+
);
|
|
1253
|
+
}
|
|
1151
1254
|
return /* @__PURE__ */ jsx(
|
|
1152
1255
|
CommentInput,
|
|
1153
1256
|
{
|
|
@@ -3470,6 +3573,10 @@ function createSDK(config) {
|
|
|
3470
3573
|
posterLoader,
|
|
3471
3574
|
comment
|
|
3472
3575
|
},
|
|
3576
|
+
guest: {
|
|
3577
|
+
isGuest: config?.guest?.mode === true,
|
|
3578
|
+
config: config?.guest
|
|
3579
|
+
},
|
|
3473
3580
|
destroy
|
|
3474
3581
|
};
|
|
3475
3582
|
}
|
|
@@ -3492,6 +3599,11 @@ function destroySDK() {
|
|
|
3492
3599
|
sdkInstance = null;
|
|
3493
3600
|
}
|
|
3494
3601
|
}
|
|
3602
|
+
async function prefetchFeed(config, options) {
|
|
3603
|
+
const debug = config.debug ?? false;
|
|
3604
|
+
const { dataSource } = resolveAdapters(config, debug);
|
|
3605
|
+
await FeedManager.prefetch(dataSource, options);
|
|
3606
|
+
}
|
|
3495
3607
|
function ShortVideoProvider({
|
|
3496
3608
|
children,
|
|
3497
3609
|
config,
|
|
@@ -3998,4 +4110,4 @@ function ShortVideoRoot({
|
|
|
3998
4110
|
}
|
|
3999
4111
|
ShortVideoRoot.displayName = "ShortVideoRoot";
|
|
4000
4112
|
|
|
4001
|
-
export { ActionBar, AuthorInfo, CommentSheet, DEFAULT_LOCALE, DefaultSlot, LocalizationAdapter, LocalizationContext, LocalizationProvider, ProgressBar, SDKPlayerError, SUPPORTED_LOCALES, ShortVideoProvider, ShortVideoRoot, VideoFeed, VideoInfo, VideoPlayer, VideoSlot, createSDK, createSimpleWireConfig, createWiredComponent, destroySDK, enMessages, getMessages, getSDK, isLocaleSupported, messageCatalogs, parseMessage, resetCommentManager, useComment, useFeed, useFeedSelector, useLifecycle, useLifecycleSelector, useLocalization, useOptimistic, useOptimisticSelector, useOptionalLocalization, useOptionalTranslation, usePlayer, usePlayerForVideo, usePlayerSelector, useResource, useResourceAllocation, useResourceSelector, useSDK, useSwipeGesture, useTranslation, viMessages };
|
|
4113
|
+
export { ActionBar, AuthorInfo, CommentSheet, DEFAULT_LOCALE, DefaultSlot, LocalizationAdapter, LocalizationContext, LocalizationProvider, ProgressBar, SDKPlayerError, SUPPORTED_LOCALES, ShortVideoProvider, ShortVideoRoot, VideoFeed, VideoInfo, VideoPlayer, VideoSlot, createSDK, createSimpleWireConfig, createWiredComponent, destroySDK, enMessages, getMessages, getSDK, isLocaleSupported, messageCatalogs, parseMessage, prefetchFeed, resetCommentManager, useComment, useFeed, useFeedSelector, useGuestMode, useLifecycle, useLifecycleSelector, useLocalization, useOptimistic, useOptimisticSelector, useOptionalLocalization, useOptionalTranslation, usePlayer, usePlayerForVideo, usePlayerSelector, useResource, useResourceAllocation, useResourceSelector, useSDK, useSwipeGesture, useTranslation, viMessages };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xhub-short/sdk",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "0.1.0-beta.
|
|
4
|
+
"version": "0.1.0-beta.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
"dist"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@xhub-short/
|
|
24
|
-
"@xhub-short/
|
|
25
|
-
"@xhub-short/
|
|
26
|
-
"@xhub-short/
|
|
23
|
+
"@xhub-short/contracts": "0.1.0-beta.5",
|
|
24
|
+
"@xhub-short/adapters": "0.1.0-beta.5",
|
|
25
|
+
"@xhub-short/core": "0.1.0-beta.5",
|
|
26
|
+
"@xhub-short/ui": "0.1.0-beta.5"
|
|
27
27
|
},
|
|
28
28
|
"optionalDependencies": {
|
|
29
|
-
"@xhub-short/bridge": "0.0.1-beta.
|
|
29
|
+
"@xhub-short/bridge": "0.0.1-beta.5"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"react": "^19.0.0",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"tsup": "^8.3.0",
|
|
43
43
|
"typescript": "^5.7.0",
|
|
44
44
|
"vitest": "^2.1.0",
|
|
45
|
-
"@xhub-short/
|
|
46
|
-
"@xhub-short/
|
|
45
|
+
"@xhub-short/vitest-config": "0.0.1-beta.4",
|
|
46
|
+
"@xhub-short/tsconfig": "0.0.0"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "tsup",
|