@xhub-short/core 0.1.0-beta.0 → 0.1.0-beta.10

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +482 -6
  2. package/dist/index.js +1095 -16
  3. package/package.json +5 -4
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { VideoItem, IDataSource, IAnalytics, ILogger, ISessionStorage, SessionSnapshot, INetworkAdapter, IVideoLoader, IPosterLoader, VideoSource, IInteraction } from '@xhub-short/contracts';
1
+ import { VideoItem, IDataSource, IStorage, PrefetchCacheData, IAnalytics, ILogger, ISessionStorage, SessionSnapshot, INetworkAdapter, IVideoLoader, IPosterLoader, VideoSource, IInteraction, CommentItem, ReplyItem, ICommentAdapter, InternalLogger, CommentAuthor } from '@xhub-short/contracts';
2
2
  export { SessionSnapshot } from '@xhub-short/contracts';
3
3
  import { StoreApi } from 'zustand/vanilla';
4
4
 
@@ -68,6 +68,58 @@ interface FeedConfig {
68
68
  * Default feed configuration
69
69
  */
70
70
  declare const DEFAULT_FEED_CONFIG: Required<FeedConfig>;
71
+ /**
72
+ * Configuration for prefetch cache feature
73
+ *
74
+ * Enables instant feed loading on fresh app open by caching
75
+ * the last N videos and showing them immediately while
76
+ * fresh data is fetched in the background.
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * const prefetchConfig: PrefetchCacheConfig = {
81
+ * enabled: true,
82
+ * maxVideos: 15,
83
+ * enableDynamicEviction: true,
84
+ * evictionThrottleMs: 2000,
85
+ * };
86
+ * ```
87
+ */
88
+ interface PrefetchCacheConfig {
89
+ /**
90
+ * Enable prefetch cache for instant loading
91
+ * @default true
92
+ */
93
+ enabled: boolean;
94
+ /**
95
+ * Maximum number of videos to cache
96
+ * Higher = more instant content, but more storage
97
+ * @default 10
98
+ */
99
+ maxVideos: number;
100
+ /**
101
+ * Storage key for prefetch cache
102
+ * @default 'sv-prefetch-cache'
103
+ */
104
+ storageKey: string;
105
+ /**
106
+ * Enable dynamic cache eviction
107
+ * When user scrolls past cached videos, remove them from cache
108
+ * Prevents user from rewatching same videos on reload
109
+ * @default true
110
+ */
111
+ enableDynamicEviction: boolean;
112
+ /**
113
+ * Throttle duration (ms) for dynamic eviction
114
+ * Reduces storage writes when user scrolls quickly
115
+ * @default 2000
116
+ */
117
+ evictionThrottleMs: number;
118
+ }
119
+ /**
120
+ * Default prefetch cache configuration
121
+ */
122
+ declare const DEFAULT_PREFETCH_CACHE_CONFIG: PrefetchCacheConfig;
71
123
 
72
124
  /**
73
125
  * FeedManager - Manages video feed data with zustand/vanilla store
@@ -101,6 +153,10 @@ declare class FeedManager {
101
153
  readonly store: StoreApi<FeedState>;
102
154
  /** Resolved configuration */
103
155
  private readonly config;
156
+ /** Prefetch cache configuration */
157
+ private readonly prefetchConfig;
158
+ /** Storage adapter for prefetch cache (optional) */
159
+ private readonly storage;
104
160
  /** Abort controller for cancelling in-flight requests */
105
161
  private abortController;
106
162
  /**
@@ -113,7 +169,26 @@ declare class FeedManager {
113
169
  * Used for garbage collection
114
170
  */
115
171
  private accessOrder;
116
- constructor(dataSource: IDataSource, config?: FeedConfig);
172
+ constructor(dataSource: IDataSource, config?: FeedConfig, storage?: IStorage, prefetchConfig?: Partial<PrefetchCacheConfig>);
173
+ /** Static memory cache for explicit prefetching */
174
+ private static globalMemoryCache;
175
+ /**
176
+ * Prefetch feed data and store in global memory cache
177
+ *
178
+ * @param dataSource - Data source to fetch from
179
+ * @param options - Prefetch options
180
+ */
181
+ static prefetch(dataSource: IDataSource, options?: {
182
+ ttl?: number;
183
+ }): Promise<void>;
184
+ /**
185
+ * Check if prefetch cache exists and is valid
186
+ */
187
+ static hasPrefetchCache(): boolean;
188
+ /**
189
+ * Clear prefetch cache
190
+ */
191
+ static clearPrefetchCache(): void;
117
192
  /**
118
193
  * Load initial feed data
119
194
  *
@@ -179,6 +254,61 @@ declare class FeedManager {
179
254
  * Destroy the manager and cleanup
180
255
  */
181
256
  destroy(): void;
257
+ /**
258
+ * Hydrate feed from a session snapshot
259
+ *
260
+ * Used by LifecycleManager to restore state without API call.
261
+ * This bypasses normal data flow for state restoration.
262
+ *
263
+ * @param items - Video items from snapshot
264
+ * @param cursor - Pagination cursor from snapshot
265
+ * @param options - Additional hydration options
266
+ */
267
+ hydrateFromSnapshot(items: VideoItem[], cursor: string | null, options?: {
268
+ /** Whether to mark data as stale for background revalidation */
269
+ markAsStale?: boolean;
270
+ }): void;
271
+ /**
272
+ * Update prefetch cache with current feed tail
273
+ * Called automatically after loadInitial() and loadMore()
274
+ *
275
+ * Strategy: Cache the LAST N videos (tail of feed)
276
+ * These are videos user hasn't seen yet, perfect for instant display
277
+ */
278
+ updatePrefetchCache(): void;
279
+ /**
280
+ * Save prefetch cache to storage (async, non-blocking)
281
+ */
282
+ private savePrefetchCacheAsync;
283
+ /**
284
+ * Load prefetch cache from storage
285
+ * Returns null if no cache, disabled, or storage error
286
+ */
287
+ loadPrefetchCache(): Promise<PrefetchCacheData | null>;
288
+ /**
289
+ * Hydrate feed from prefetch cache for instant display
290
+ * Marks data as stale to trigger background revalidation
291
+ */
292
+ hydrateFromPrefetchCache(cache: PrefetchCacheData): void;
293
+ /**
294
+ * Clear prefetch cache
295
+ * Call when user logs out or data should be invalidated
296
+ */
297
+ clearPrefetchCache(): Promise<void>;
298
+ /**
299
+ * Evict videos that user has scrolled past from prefetch cache
300
+ * Called when user's focusedIndex changes
301
+ *
302
+ * Strategy: Remove all videos at or before current position
303
+ * This ensures user doesn't rewatch videos on reload
304
+ *
305
+ * @param currentIndex - Current focused video index in feed
306
+ */
307
+ evictViewedVideosFromCache(currentIndex: number): Promise<void>;
308
+ /**
309
+ * Get prefetch cache configuration (for external access)
310
+ */
311
+ getPrefetchConfig(): PrefetchCacheConfig;
182
312
  /**
183
313
  * Fetch with exponential backoff retry
184
314
  */
@@ -274,6 +404,8 @@ interface PlayerState {
274
404
  status: PlayerStatus;
275
405
  /** Currently loaded video */
276
406
  currentVideo: VideoItem | null;
407
+ /** Current video ID (convenience getter for currentVideo?.id) */
408
+ currentVideoId: string | null;
277
409
  /** Current playback time in seconds */
278
410
  currentTime: number;
279
411
  /** Video duration in seconds */
@@ -294,6 +426,29 @@ interface PlayerState {
294
426
  error: PlayerError | null;
295
427
  /** Whether video has ended */
296
428
  ended: boolean;
429
+ /**
430
+ * Pending restore position for session restore.
431
+ *
432
+ * When set, the next video with matching `pendingRestoreVideoId`
433
+ * should start at this position (using #t= or hls.startPosition).
434
+ *
435
+ * Cleared after being consumed by VideoPlayer.
436
+ */
437
+ pendingRestoreTime: number | null;
438
+ /**
439
+ * Video ID for pending restore position.
440
+ *
441
+ * Used to match the correct video when restoring session.
442
+ * Only the video with this ID should use `pendingRestoreTime`.
443
+ */
444
+ pendingRestoreVideoId: string | null;
445
+ /**
446
+ * Captured video frame at restore position (base64 JPEG).
447
+ *
448
+ * Displayed as instant preview while video loads.
449
+ * Cleared after being consumed by VideoPlayer/VideoSlot.
450
+ */
451
+ pendingRestoreFrame: string | null;
297
452
  }
298
453
  /**
299
454
  * PlayerEngine configuration
@@ -537,6 +692,60 @@ declare class PlayerEngine {
537
692
  * Handle video error
538
693
  */
539
694
  onError(error: Error, mediaError?: MediaError): void;
695
+ /**
696
+ * Set restore position for session restore.
697
+ *
698
+ * When the video with matching ID loads, VideoPlayer should
699
+ * use this position as startTime (via #t= or hls.startPosition).
700
+ *
701
+ * @param videoId - Video ID that should use this restore position
702
+ * @param time - Playback position in seconds
703
+ *
704
+ * @example
705
+ * ```typescript
706
+ * // During session restore
707
+ * if (result.playbackTime && result.currentVideoId) {
708
+ * playerEngine.setRestorePosition(result.currentVideoId, result.playbackTime, result.restoreFrame);
709
+ * }
710
+ * ```
711
+ */
712
+ setRestorePosition(videoId: string, time: number, frame?: string): void;
713
+ /**
714
+ * Get and clear restore position for a video.
715
+ *
716
+ * VideoPlayer calls this when rendering to get startTime.
717
+ * Position is cleared after being read to prevent reuse.
718
+ * Note: restoreFrame is NOT cleared here - use consumeRestoreFrame() separately.
719
+ *
720
+ * @param videoId - Video ID to check
721
+ * @returns Restore time in seconds, or null if no pending restore
722
+ */
723
+ consumeRestorePosition(videoId: string): number | null;
724
+ /**
725
+ * Get and clear restore frame for a video.
726
+ *
727
+ * VideoSlot calls this to display instant preview while video loads.
728
+ * Frame is cleared after being read to free memory.
729
+ *
730
+ * @param videoId - Video ID to check
731
+ * @returns Base64 JPEG data URL, or null if no pending frame
732
+ */
733
+ consumeRestoreFrame(videoId: string): string | null;
734
+ /**
735
+ * Get restore frame without consuming (peek).
736
+ * Used to display preview while keeping it available.
737
+ *
738
+ * @param videoId - Video ID to check
739
+ * @returns Base64 JPEG data URL, or null if no pending frame
740
+ */
741
+ peekRestoreFrame(videoId: string): string | null;
742
+ /**
743
+ * Check if there's a pending restore position for a video.
744
+ *
745
+ * @param videoId - Video ID to check
746
+ * @returns True if there's a pending restore position
747
+ */
748
+ hasPendingRestorePosition(videoId: string): boolean;
540
749
  /**
541
750
  * Reset player to initial state
542
751
  */
@@ -579,6 +788,7 @@ declare class PlayerEngine {
579
788
  private emitEvent;
580
789
  /**
581
790
  * Start watch time tracking
791
+ * Increments watchTime every second and sends analytics heartbeat
582
792
  */
583
793
  private startWatchTimeTracking;
584
794
  /**
@@ -586,9 +796,14 @@ declare class PlayerEngine {
586
796
  */
587
797
  private stopWatchTimeTracking;
588
798
  /**
589
- * Track completion analytics
799
+ * Track completion analytics (when video loops/ends)
590
800
  */
591
801
  private trackCompletion;
802
+ /**
803
+ * Track when user leaves current video (scrolls to next video)
804
+ * Sends final analytics event before video change
805
+ */
806
+ private trackLeaveVideo;
592
807
  /**
593
808
  * Categorize media error
594
809
  */
@@ -697,6 +912,8 @@ interface RestoreResult {
697
912
  playbackTime?: number;
698
913
  /** Video ID that was playing (only present if restorePlaybackPosition config is enabled) */
699
914
  currentVideoId?: string;
915
+ /** Captured video frame at playback position (base64 JPEG, only present if restorePlaybackPosition is enabled) */
916
+ restoreFrame?: string;
700
917
  }
701
918
  /**
702
919
  * LifecycleManager configuration
@@ -819,6 +1036,7 @@ declare class LifecycleManager {
819
1036
  * @param data - Snapshot data to save
820
1037
  * @param data.playbackTime - Current video playback position (only saved if restorePlaybackPosition config is enabled)
821
1038
  * @param data.currentVideoId - Current video ID (only saved if restorePlaybackPosition config is enabled)
1039
+ * @param data.restoreFrame - Captured video frame at playback position (only saved if restorePlaybackPosition is enabled)
822
1040
  */
823
1041
  saveSnapshot(data: {
824
1042
  items: VideoItem[];
@@ -829,6 +1047,8 @@ declare class LifecycleManager {
829
1047
  playbackTime?: number;
830
1048
  /** Current video ID (only used when restorePlaybackPosition is enabled) */
831
1049
  currentVideoId?: string;
1050
+ /** Captured video frame at playback position (only used when restorePlaybackPosition is enabled) */
1051
+ restoreFrame?: string;
832
1052
  }): Promise<boolean>;
833
1053
  /**
834
1054
  * Clear saved snapshot
@@ -1352,6 +1572,10 @@ declare class OptimisticManager {
1352
1572
  private readonly eventListeners;
1353
1573
  /** Retry timer */
1354
1574
  private retryTimer;
1575
+ /** Debounce timers for like/unlike per video */
1576
+ private readonly likeDebounceTimers;
1577
+ /** Debounce delay in ms */
1578
+ private readonly debounceDelay;
1355
1579
  constructor(config?: OptimisticConfig);
1356
1580
  /**
1357
1581
  * Like a video with optimistic update
@@ -1362,9 +1586,26 @@ declare class OptimisticManager {
1362
1586
  */
1363
1587
  unlike(videoId: string): Promise<boolean>;
1364
1588
  /**
1365
- * Toggle like state (like if not liked, unlike if liked)
1589
+ * Toggle like state with DEBOUNCE (like if not liked, unlike if liked)
1590
+ *
1591
+ * This method:
1592
+ * 1. Updates UI immediately (optimistic)
1593
+ * 2. Debounces API call - only sends after user stops clicking
1594
+ * 3. Sends final state to API after debounce delay
1595
+ *
1596
+ * Perfect for rapid tapping like TikTok/Instagram behavior.
1366
1597
  */
1367
- toggleLike(videoId: string): Promise<boolean>;
1598
+ toggleLike(videoId: string): void;
1599
+ /**
1600
+ * Execute the actual API call after debounce
1601
+ * Reads current state from FeedManager to get final intended state
1602
+ */
1603
+ private executeDebouncedLikeApi;
1604
+ /**
1605
+ * @deprecated Use toggleLike() instead - it now includes debounce
1606
+ * Legacy toggle that waits for API response
1607
+ */
1608
+ toggleLikeSync(videoId: string): Promise<boolean>;
1368
1609
  /**
1369
1610
  * Follow a video author with optimistic update
1370
1611
  */
@@ -1383,6 +1624,7 @@ declare class OptimisticManager {
1383
1624
  getPendingActions(): PendingAction[];
1384
1625
  /**
1385
1626
  * Check if there's a pending action for a video
1627
+ * Only returns true for actions with status 'pending' (not 'failed')
1386
1628
  */
1387
1629
  hasPendingAction(videoId: string, type?: ActionType): boolean;
1388
1630
  /**
@@ -1463,4 +1705,238 @@ declare class OptimisticManager {
1463
1705
  private emitEvent;
1464
1706
  }
1465
1707
 
1466
- export { type ActionType, type AllocationResult, DEFAULT_FEED_CONFIG, DEFAULT_LIFECYCLE_CONFIG, DEFAULT_OPTIMISTIC_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_PREFETCH_CONFIG, DEFAULT_RESOURCE_CONFIG, type FeedConfig, type FeedError, FeedManager, type FeedState, type LifecycleConfig, type LifecycleEvent, type LifecycleEventListener, LifecycleManager, type LifecycleState, type NetworkType, type OptimisticConfig, type OptimisticEvent, type OptimisticEventListener, OptimisticManager, type OptimisticState, type PendingAction, type PlayerConfig, PlayerEngine, type PlayerError, type PlayerEvent, type PlayerEventListener, type PlayerState, PlayerStatus, type PrefetchConfig, type ResourceConfig, type ResourceEvent, type ResourceEventListener, ResourceGovernor, type ResourceState, type RestoreResult, calculatePrefetchIndices, calculateWindowIndices, canPause, canPlay, canSeek, computeAllocationChanges, isActiveState, isValidTransition, mapNetworkType };
1708
+ /**
1709
+ * Comment state for a single video in zustand store
1710
+ */
1711
+ interface VideoCommentState {
1712
+ /** Normalized comments - Map for O(1) lookup */
1713
+ commentsById: Map<string, CommentItem>;
1714
+ /** Ordered list of comment IDs for rendering */
1715
+ displayOrder: string[];
1716
+ /** Total comment count from API */
1717
+ totalCount: number;
1718
+ /** Cursor for pagination */
1719
+ cursor: string | null;
1720
+ /** Whether more comments can be loaded */
1721
+ hasMore: boolean;
1722
+ /** Initial loading state */
1723
+ loading: boolean;
1724
+ /** Loading more (pagination) state */
1725
+ loadingMore: boolean;
1726
+ /** Error state */
1727
+ error: CommentError | null;
1728
+ /** Cache timestamp for TTL */
1729
+ cachedAt: number;
1730
+ /** Whether data is stale */
1731
+ isStale: boolean;
1732
+ }
1733
+ /**
1734
+ * Global comment manager state
1735
+ */
1736
+ interface CommentManagerState {
1737
+ /** Comments by video ID */
1738
+ byVideoId: Map<string, VideoCommentState>;
1739
+ /** Currently active video ID (for comment sheet) */
1740
+ activeVideoId: string | null;
1741
+ /** Posting state */
1742
+ isPosting: boolean;
1743
+ /** Posting error */
1744
+ postError: CommentError | null;
1745
+ /** Deleting comment ID (for optimistic UI) */
1746
+ deletingId: string | null;
1747
+ }
1748
+ /**
1749
+ * Comment error with additional context
1750
+ */
1751
+ interface CommentError {
1752
+ /** Error message */
1753
+ message: string;
1754
+ /** Error code for programmatic handling */
1755
+ code: 'NETWORK_ERROR' | 'TIMEOUT' | 'SERVER_ERROR' | 'NOT_FOUND' | 'FORBIDDEN' | 'RATE_LIMITED' | 'UNKNOWN';
1756
+ /** Number of retry attempts made */
1757
+ retryCount: number;
1758
+ /** Whether error is recoverable */
1759
+ recoverable: boolean;
1760
+ }
1761
+ /**
1762
+ * CommentManager configuration
1763
+ */
1764
+ interface CommentManagerConfig {
1765
+ /** Comments per page (default: 20) */
1766
+ pageSize?: number;
1767
+ /** Replies per load (default: 10) */
1768
+ repliesPageSize?: number;
1769
+ /** Cache TTL in ms (default: 5 minutes) */
1770
+ cacheTTL?: number;
1771
+ /** Maximum retry attempts (default: 2) */
1772
+ maxRetries?: number;
1773
+ /** Auto-expand threshold for replies (default: 1) */
1774
+ repliesAutoExpandThreshold?: number;
1775
+ /** Replies collapse limit (default: 3) */
1776
+ repliesCollapseLimit?: number;
1777
+ /** Comment text max lines before collapse (default: 3) */
1778
+ textMaxLines?: number;
1779
+ /** Enable optimistic UI (default: true) */
1780
+ enableOptimistic?: boolean;
1781
+ }
1782
+ /**
1783
+ * Default comment manager configuration
1784
+ */
1785
+ declare const DEFAULT_COMMENT_MANAGER_CONFIG: Required<CommentManagerConfig>;
1786
+ /**
1787
+ * Create initial state for a video's comments
1788
+ */
1789
+ declare const createInitialVideoCommentState: () => VideoCommentState;
1790
+ /**
1791
+ * Create initial global comment state
1792
+ */
1793
+ declare const createInitialCommentState: () => CommentManagerState;
1794
+ /**
1795
+ * Optimistic comment for immediate UI feedback
1796
+ */
1797
+ interface OptimisticComment extends Omit<CommentItem, 'id'> {
1798
+ /** Temporary optimistic ID (prefixed with 'optimistic_') */
1799
+ id: string;
1800
+ /** Flag to identify optimistic items */
1801
+ isPending: true;
1802
+ }
1803
+ /**
1804
+ * Optimistic reply for immediate UI feedback
1805
+ */
1806
+ interface OptimisticReply extends Omit<ReplyItem, 'id'> {
1807
+ /** Temporary optimistic ID */
1808
+ id: string;
1809
+ /** Flag to identify optimistic items */
1810
+ isPending: true;
1811
+ }
1812
+
1813
+ /**
1814
+ * CommentManager - Manages comment data with zustand/vanilla store
1815
+ *
1816
+ * Features:
1817
+ * - Multi-video comment caching (by videoId)
1818
+ * - Pagination with cursor
1819
+ * - Nested replies support (1 level)
1820
+ * - Optimistic UI for post/delete
1821
+ * - Cache TTL for stale data detection
1822
+ * - Request deduplication
1823
+ *
1824
+ * Architecture: Hexagonal (Port = ICommentAdapter)
1825
+ *
1826
+ * @example
1827
+ * ```typescript
1828
+ * const commentManager = new CommentManager(commentAdapter);
1829
+ *
1830
+ * // Subscribe to state changes
1831
+ * commentManager.store.subscribe((state) => console.log(state));
1832
+ *
1833
+ * // Load comments for a video
1834
+ * await commentManager.loadComments('video-123');
1835
+ *
1836
+ * // Post a comment
1837
+ * await commentManager.postComment('video-123', 'Great video!');
1838
+ * ```
1839
+ */
1840
+ declare class CommentManager {
1841
+ private readonly adapter;
1842
+ /** Zustand vanilla store - Single Source of Truth */
1843
+ readonly store: StoreApi<CommentManagerState>;
1844
+ /** Resolved configuration */
1845
+ private readonly config;
1846
+ /** Logger (optional) */
1847
+ private readonly logger?;
1848
+ /** Request deduplication: Map of key → in-flight Promise */
1849
+ private inFlightRequests;
1850
+ /** Optimistic ID counter */
1851
+ private optimisticIdCounter;
1852
+ constructor(adapter: ICommentAdapter, config?: CommentManagerConfig, logger?: InternalLogger);
1853
+ /**
1854
+ * Load comments for a video
1855
+ *
1856
+ * Features:
1857
+ * - Cache check with TTL
1858
+ * - Request deduplication
1859
+ * - Stale data detection
1860
+ */
1861
+ loadComments(videoId: string, forceRefresh?: boolean): Promise<void>;
1862
+ /**
1863
+ * Load more comments (pagination)
1864
+ */
1865
+ loadMore(videoId: string): Promise<void>;
1866
+ /**
1867
+ * Load replies for a comment
1868
+ */
1869
+ loadReplies(commentId: string): Promise<void>;
1870
+ /**
1871
+ * Post a new comment with optimistic UI
1872
+ */
1873
+ postComment(videoId: string, content: string, currentUser: CommentAuthor): Promise<CommentItem | null>;
1874
+ /**
1875
+ * Post a reply with optimistic UI
1876
+ */
1877
+ postReply(videoId: string, parentId: string, content: string, currentUser: CommentAuthor, replyTo?: CommentAuthor): Promise<ReplyItem | null>;
1878
+ /**
1879
+ * Delete a comment with optimistic UI
1880
+ */
1881
+ deleteComment(videoId: string, commentId: string, isReply?: boolean, parentId?: string): Promise<boolean>;
1882
+ /**
1883
+ * Like a comment/reply with optimistic UI
1884
+ */
1885
+ likeComment(videoId: string, commentId: string, isReply?: boolean, parentId?: string): Promise<void>;
1886
+ /**
1887
+ * Unlike a comment/reply with optimistic UI
1888
+ */
1889
+ unlikeComment(videoId: string, commentId: string, isReply?: boolean, parentId?: string): Promise<void>;
1890
+ /**
1891
+ * Get comments for a video
1892
+ */
1893
+ getComments(videoId: string): CommentItem[];
1894
+ /**
1895
+ * Get a single comment
1896
+ */
1897
+ getComment(videoId: string, commentId: string): CommentItem | undefined;
1898
+ /**
1899
+ * Get a single reply
1900
+ */
1901
+ getReply(videoId: string, parentId: string, replyId: string): ReplyItem | undefined;
1902
+ /**
1903
+ * Get video comment state
1904
+ */
1905
+ getVideoState(videoId: string): VideoCommentState | undefined;
1906
+ /**
1907
+ * Set active video ID (for comment sheet)
1908
+ */
1909
+ setActiveVideo(videoId: string | null): void;
1910
+ /**
1911
+ * Get config
1912
+ */
1913
+ getConfig(): Required<CommentManagerConfig>;
1914
+ /**
1915
+ * Clear comments for a video
1916
+ */
1917
+ clearVideoComments(videoId: string): void;
1918
+ /**
1919
+ * Clear all comments
1920
+ */
1921
+ clearAll(): void;
1922
+ private executeLoadComments;
1923
+ private executeLoadMore;
1924
+ private executeLoadReplies;
1925
+ private addOptimisticComment;
1926
+ private removeOptimisticComment;
1927
+ private replaceOptimisticComment;
1928
+ private addOptimisticReply;
1929
+ private removeOptimisticReply;
1930
+ private replaceOptimisticReply;
1931
+ private removeCommentFromStore;
1932
+ private removeReplyFromStore;
1933
+ private restoreComment;
1934
+ private restoreReply;
1935
+ private updateLikeState;
1936
+ private updateVideoState;
1937
+ private isCacheStale;
1938
+ private generateOptimisticId;
1939
+ private createError;
1940
+ }
1941
+
1942
+ export { type ActionType, type AllocationResult, type CommentError, CommentManager, type CommentManagerConfig, type CommentManagerState, DEFAULT_COMMENT_MANAGER_CONFIG, DEFAULT_FEED_CONFIG, DEFAULT_LIFECYCLE_CONFIG, DEFAULT_OPTIMISTIC_CONFIG, DEFAULT_PLAYER_CONFIG, DEFAULT_PREFETCH_CACHE_CONFIG, DEFAULT_PREFETCH_CONFIG, DEFAULT_RESOURCE_CONFIG, type FeedConfig, type FeedError, FeedManager, type FeedState, type LifecycleConfig, type LifecycleEvent, type LifecycleEventListener, LifecycleManager, type LifecycleState, type NetworkType, type OptimisticComment, type OptimisticConfig, type OptimisticEvent, type OptimisticEventListener, OptimisticManager, type OptimisticReply, type OptimisticState, type PendingAction, type PlayerConfig, PlayerEngine, type PlayerError, type PlayerEvent, type PlayerEventListener, type PlayerState, PlayerStatus, type PrefetchCacheConfig, type PrefetchConfig, type ResourceConfig, type ResourceEvent, type ResourceEventListener, ResourceGovernor, type ResourceState, type RestoreResult, type VideoCommentState, calculatePrefetchIndices, calculateWindowIndices, canPause, canPlay, canSeek, computeAllocationChanges, createInitialCommentState, createInitialVideoCommentState, isActiveState, isValidTransition, mapNetworkType };