@xhub-short/contracts 0.1.0-beta.1 → 0.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +712 -1
- package/dist/index.js +27 -0
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -190,6 +190,13 @@ interface SessionSnapshot {
|
|
|
190
190
|
* Backup for focusedIndex in case feed order changed
|
|
191
191
|
*/
|
|
192
192
|
currentVideoId?: string;
|
|
193
|
+
/**
|
|
194
|
+
* Captured video frame at playback position (base64 JPEG)
|
|
195
|
+
* Used to show instant preview while video loads on restore
|
|
196
|
+
* Only saved when restorePlaybackPosition config is enabled
|
|
197
|
+
* Max size: ~100KB (compressed JPEG, quality 60%)
|
|
198
|
+
*/
|
|
199
|
+
restoreFrame?: string;
|
|
193
200
|
/** Snapshot creation time */
|
|
194
201
|
savedAt: number;
|
|
195
202
|
/** SDK version for compatibility checking */
|
|
@@ -287,6 +294,236 @@ interface LogEntry {
|
|
|
287
294
|
stack?: string;
|
|
288
295
|
}
|
|
289
296
|
|
|
297
|
+
/**
|
|
298
|
+
* Comment Feature Types
|
|
299
|
+
* Supports nested replies (1 level), pagination, and optimistic updates
|
|
300
|
+
*/
|
|
301
|
+
/**
|
|
302
|
+
* Full comment item with replies support
|
|
303
|
+
*/
|
|
304
|
+
interface CommentItem {
|
|
305
|
+
/** Unique comment ID */
|
|
306
|
+
id: string;
|
|
307
|
+
/** Video ID this comment belongs to */
|
|
308
|
+
videoId: string;
|
|
309
|
+
/** Comment text content */
|
|
310
|
+
content: string;
|
|
311
|
+
/** Comment author */
|
|
312
|
+
author: CommentAuthor;
|
|
313
|
+
/** Like count */
|
|
314
|
+
likeCount: number;
|
|
315
|
+
/** Whether current user liked this comment */
|
|
316
|
+
isLiked: boolean;
|
|
317
|
+
/** Total reply count */
|
|
318
|
+
replyCount: number;
|
|
319
|
+
/** Loaded replies (may be partial) */
|
|
320
|
+
replies?: ReplyItem[];
|
|
321
|
+
/** Cursor for loading more replies */
|
|
322
|
+
repliesCursor?: string | null;
|
|
323
|
+
/** Whether all replies are loaded */
|
|
324
|
+
repliesLoaded?: boolean;
|
|
325
|
+
/** Creation timestamp (ISO 8601) */
|
|
326
|
+
createdAt: string;
|
|
327
|
+
/** Last updated timestamp (ISO 8601) */
|
|
328
|
+
updatedAt?: string;
|
|
329
|
+
/** Whether this is user's own comment (for edit/delete) */
|
|
330
|
+
isOwner?: boolean;
|
|
331
|
+
/** Whether this comment is pending (optimistic) */
|
|
332
|
+
isPending?: boolean;
|
|
333
|
+
/** Optional: Parent comment ID (for flat list with parent reference) */
|
|
334
|
+
parentId?: string | null;
|
|
335
|
+
/** Whether this comment is pinned by video author */
|
|
336
|
+
isPinned?: boolean;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Reply item (Level 1 nested comment)
|
|
340
|
+
*/
|
|
341
|
+
interface ReplyItem {
|
|
342
|
+
/** Unique reply ID */
|
|
343
|
+
id: string;
|
|
344
|
+
/** Parent comment ID */
|
|
345
|
+
parentId: string;
|
|
346
|
+
/** Reply text content */
|
|
347
|
+
content: string;
|
|
348
|
+
/** Reply author */
|
|
349
|
+
author: CommentAuthor;
|
|
350
|
+
/** Like count */
|
|
351
|
+
likeCount: number;
|
|
352
|
+
/** Whether current user liked this reply */
|
|
353
|
+
isLiked: boolean;
|
|
354
|
+
/** User being replied to (for @mention) */
|
|
355
|
+
replyTo?: CommentAuthor;
|
|
356
|
+
/** Creation timestamp (ISO 8601) */
|
|
357
|
+
createdAt: string;
|
|
358
|
+
/** Whether this is user's own reply */
|
|
359
|
+
isOwner?: boolean;
|
|
360
|
+
/** Whether this reply is pending (optimistic) */
|
|
361
|
+
isPending?: boolean;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Comment author (may differ from video Author)
|
|
365
|
+
*/
|
|
366
|
+
interface CommentAuthor {
|
|
367
|
+
/** Unique author ID */
|
|
368
|
+
id: string;
|
|
369
|
+
/** Display name */
|
|
370
|
+
name: string;
|
|
371
|
+
/** Avatar URL */
|
|
372
|
+
avatar?: string;
|
|
373
|
+
/** Verified status */
|
|
374
|
+
isVerified?: boolean;
|
|
375
|
+
/** Additional badge (e.g., "Creator", "Top Fan") */
|
|
376
|
+
badge?: string;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Response for listing comments
|
|
380
|
+
*/
|
|
381
|
+
interface CommentListResponse {
|
|
382
|
+
/** List of comments */
|
|
383
|
+
items: CommentItem[];
|
|
384
|
+
/** Total comment count for this video */
|
|
385
|
+
totalCount: number;
|
|
386
|
+
/** Cursor for next page (null if no more) */
|
|
387
|
+
nextCursor: string | null;
|
|
388
|
+
/** Whether there are more comments */
|
|
389
|
+
hasMore: boolean;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Response for listing replies
|
|
393
|
+
*/
|
|
394
|
+
interface ReplyListResponse {
|
|
395
|
+
/** List of replies */
|
|
396
|
+
items: ReplyItem[];
|
|
397
|
+
/** Parent comment ID */
|
|
398
|
+
parentId: string;
|
|
399
|
+
/** Cursor for next page */
|
|
400
|
+
nextCursor: string | null;
|
|
401
|
+
/** Whether there are more replies */
|
|
402
|
+
hasMore: boolean;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Payload for posting a new comment
|
|
406
|
+
*/
|
|
407
|
+
interface PostCommentPayload {
|
|
408
|
+
/** Video ID */
|
|
409
|
+
videoId: string;
|
|
410
|
+
/** Comment content */
|
|
411
|
+
content: string;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Payload for posting a reply
|
|
415
|
+
*/
|
|
416
|
+
interface PostReplyPayload {
|
|
417
|
+
/** Video ID */
|
|
418
|
+
videoId: string;
|
|
419
|
+
/** Parent comment ID */
|
|
420
|
+
parentId: string;
|
|
421
|
+
/** Reply content */
|
|
422
|
+
content: string;
|
|
423
|
+
/** Optional: User being replied to */
|
|
424
|
+
replyToUserId?: string;
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Payload for editing a comment/reply
|
|
428
|
+
*/
|
|
429
|
+
interface EditCommentPayload {
|
|
430
|
+
/** Comment/Reply ID */
|
|
431
|
+
id: string;
|
|
432
|
+
/** New content */
|
|
433
|
+
content: string;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Payload for deleting a comment/reply
|
|
437
|
+
*/
|
|
438
|
+
interface DeleteCommentPayload {
|
|
439
|
+
/** Comment/Reply ID */
|
|
440
|
+
id: string;
|
|
441
|
+
/** Whether this is a reply (affects API endpoint) */
|
|
442
|
+
isReply?: boolean;
|
|
443
|
+
/** Parent comment ID (required if isReply) */
|
|
444
|
+
parentId?: string;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Payload for reporting a comment
|
|
448
|
+
*/
|
|
449
|
+
interface ReportCommentPayload {
|
|
450
|
+
/** Comment/Reply ID */
|
|
451
|
+
id: string;
|
|
452
|
+
/** Report reason */
|
|
453
|
+
reason: CommentReportReason;
|
|
454
|
+
/** Additional description */
|
|
455
|
+
description?: string;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Comment report reasons
|
|
459
|
+
*/
|
|
460
|
+
type CommentReportReason = 'spam' | 'harassment' | 'hate_speech' | 'misinformation' | 'inappropriate' | 'other';
|
|
461
|
+
/**
|
|
462
|
+
* Comment state for a single video
|
|
463
|
+
*/
|
|
464
|
+
interface CommentState {
|
|
465
|
+
/** Video ID */
|
|
466
|
+
videoId: string;
|
|
467
|
+
/** Comments map by ID */
|
|
468
|
+
commentsMap: Map<string, CommentItem>;
|
|
469
|
+
/** Ordered comment IDs */
|
|
470
|
+
orderedIds: string[];
|
|
471
|
+
/** Total count from API */
|
|
472
|
+
totalCount: number;
|
|
473
|
+
/** Pagination cursor */
|
|
474
|
+
cursor: string | null;
|
|
475
|
+
/** Whether more comments can be loaded */
|
|
476
|
+
hasMore: boolean;
|
|
477
|
+
/** Loading state */
|
|
478
|
+
isLoading: boolean;
|
|
479
|
+
/** Loading more state */
|
|
480
|
+
isLoadingMore: boolean;
|
|
481
|
+
/** Error state */
|
|
482
|
+
error: Error | null;
|
|
483
|
+
/** Cache timestamp for TTL */
|
|
484
|
+
cachedAt: number;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Global comment manager state
|
|
488
|
+
*/
|
|
489
|
+
interface CommentManagerState {
|
|
490
|
+
/** Comments by video ID */
|
|
491
|
+
commentsByVideo: Map<string, CommentState>;
|
|
492
|
+
/** Currently active video ID (for comment sheet) */
|
|
493
|
+
activeVideoId: string | null;
|
|
494
|
+
/** Posting state */
|
|
495
|
+
isPosting: boolean;
|
|
496
|
+
/** Posting error */
|
|
497
|
+
postError: Error | null;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Comment feature configuration
|
|
501
|
+
*/
|
|
502
|
+
interface CommentConfig {
|
|
503
|
+
/** Comments per page (default: 20) */
|
|
504
|
+
pageSize: number;
|
|
505
|
+
/** Replies per page (default: 10) */
|
|
506
|
+
replyPageSize: number;
|
|
507
|
+
/** Cache TTL in ms (default: 5 minutes) */
|
|
508
|
+
cacheTTL: number;
|
|
509
|
+
/** Auto-expand threshold for replies (default: 1) */
|
|
510
|
+
repliesAutoExpandThreshold: number;
|
|
511
|
+
/** Replies collapse limit (default: 3) */
|
|
512
|
+
repliesCollapseLimit: number;
|
|
513
|
+
/** Comment text max lines before collapse (default: 3) */
|
|
514
|
+
textMaxLines: number;
|
|
515
|
+
/** Input max length (default: 500) */
|
|
516
|
+
inputMaxLength: number;
|
|
517
|
+
/** Enable optimistic UI (default: true) */
|
|
518
|
+
enableOptimisticUI: boolean;
|
|
519
|
+
/** Require delete confirmation (default: true) */
|
|
520
|
+
requireDeleteConfirm: boolean;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Default comment configuration
|
|
524
|
+
*/
|
|
525
|
+
declare const DEFAULT_COMMENT_CONFIG: CommentConfig;
|
|
526
|
+
|
|
290
527
|
/**
|
|
291
528
|
* IDataSource - Data Port Interface
|
|
292
529
|
*
|
|
@@ -472,6 +709,39 @@ interface IInteraction {
|
|
|
472
709
|
report?(videoId: string, reason: string, description?: string): Promise<void>;
|
|
473
710
|
}
|
|
474
711
|
|
|
712
|
+
/**
|
|
713
|
+
* Data structure for prefetch cache
|
|
714
|
+
*
|
|
715
|
+
* Stored in localStorage for instant feed loading on fresh app open.
|
|
716
|
+
* Contains video metadata (NOT video data) for immediate display.
|
|
717
|
+
*
|
|
718
|
+
* @example
|
|
719
|
+
* ```typescript
|
|
720
|
+
* const cacheData: PrefetchCacheData = {
|
|
721
|
+
* items: [video1, video2, ...], // Last N videos from feed
|
|
722
|
+
* savedAt: Date.now(),
|
|
723
|
+
* cursor: 'abc123',
|
|
724
|
+
* };
|
|
725
|
+
* await storage.set('sv-prefetch-cache', cacheData);
|
|
726
|
+
* ```
|
|
727
|
+
*/
|
|
728
|
+
interface PrefetchCacheData {
|
|
729
|
+
/**
|
|
730
|
+
* Cached video items (tail of feed - videos user hasn't seen)
|
|
731
|
+
* These are shown instantly on fresh load
|
|
732
|
+
*/
|
|
733
|
+
items: VideoItem[];
|
|
734
|
+
/**
|
|
735
|
+
* Timestamp when cache was saved
|
|
736
|
+
* Used for debugging and potential TTL features
|
|
737
|
+
*/
|
|
738
|
+
savedAt: number;
|
|
739
|
+
/**
|
|
740
|
+
* Pagination cursor for continuing from cached position
|
|
741
|
+
* Allows loadMore() to work correctly after hydrating from cache
|
|
742
|
+
*/
|
|
743
|
+
cursor: string | null;
|
|
744
|
+
}
|
|
475
745
|
/**
|
|
476
746
|
* IStorage - Storage Port Interface
|
|
477
747
|
*
|
|
@@ -1043,6 +1313,258 @@ interface IPosterLoader {
|
|
|
1043
1313
|
clearCache(): void;
|
|
1044
1314
|
}
|
|
1045
1315
|
|
|
1316
|
+
/**
|
|
1317
|
+
* Comment Adapter Interface (Port)
|
|
1318
|
+
* Defines the contract for comment data operations
|
|
1319
|
+
* Host app can implement this interface or use preset REST adapter
|
|
1320
|
+
*/
|
|
1321
|
+
|
|
1322
|
+
/**
|
|
1323
|
+
* Comment adapter interface (Port in Hexagonal Architecture)
|
|
1324
|
+
* All comment operations go through this interface
|
|
1325
|
+
*/
|
|
1326
|
+
interface ICommentAdapter {
|
|
1327
|
+
/**
|
|
1328
|
+
* Get comments for a video
|
|
1329
|
+
* @param videoId - Video ID
|
|
1330
|
+
* @param cursor - Pagination cursor (null for first page)
|
|
1331
|
+
* @param limit - Number of comments per page
|
|
1332
|
+
* @returns Paginated comment list
|
|
1333
|
+
*/
|
|
1334
|
+
getComments(videoId: string, cursor?: string | null, limit?: number): Promise<CommentListResponse>;
|
|
1335
|
+
/**
|
|
1336
|
+
* Get replies for a comment
|
|
1337
|
+
* @param commentId - Parent comment ID
|
|
1338
|
+
* @param cursor - Pagination cursor
|
|
1339
|
+
* @param limit - Number of replies per page
|
|
1340
|
+
* @returns Paginated reply list
|
|
1341
|
+
*/
|
|
1342
|
+
getReplies(commentId: string, cursor?: string | null, limit?: number): Promise<ReplyListResponse>;
|
|
1343
|
+
/**
|
|
1344
|
+
* Post a new comment
|
|
1345
|
+
* @param payload - Comment data
|
|
1346
|
+
* @returns Created comment
|
|
1347
|
+
*/
|
|
1348
|
+
postComment(payload: PostCommentPayload): Promise<CommentItem>;
|
|
1349
|
+
/**
|
|
1350
|
+
* Post a reply to a comment
|
|
1351
|
+
* @param payload - Reply data
|
|
1352
|
+
* @returns Created reply
|
|
1353
|
+
*/
|
|
1354
|
+
postReply(payload: PostReplyPayload): Promise<ReplyItem>;
|
|
1355
|
+
/**
|
|
1356
|
+
* Edit an existing comment/reply
|
|
1357
|
+
* @param payload - Edit data
|
|
1358
|
+
* @returns Updated comment/reply
|
|
1359
|
+
*/
|
|
1360
|
+
editComment(payload: EditCommentPayload): Promise<CommentItem | ReplyItem>;
|
|
1361
|
+
/**
|
|
1362
|
+
* Delete a comment/reply
|
|
1363
|
+
* @param payload - Delete data
|
|
1364
|
+
*/
|
|
1365
|
+
deleteComment(payload: DeleteCommentPayload): Promise<void>;
|
|
1366
|
+
/**
|
|
1367
|
+
* Like a comment/reply
|
|
1368
|
+
* @param id - Comment/Reply ID
|
|
1369
|
+
*/
|
|
1370
|
+
likeComment(id: string): Promise<void>;
|
|
1371
|
+
/**
|
|
1372
|
+
* Unlike a comment/reply
|
|
1373
|
+
* @param id - Comment/Reply ID
|
|
1374
|
+
*/
|
|
1375
|
+
unlikeComment(id: string): Promise<void>;
|
|
1376
|
+
/**
|
|
1377
|
+
* Report a comment/reply
|
|
1378
|
+
* @param payload - Report data
|
|
1379
|
+
*/
|
|
1380
|
+
reportComment(payload: ReportCommentPayload): Promise<void>;
|
|
1381
|
+
}
|
|
1382
|
+
/**
|
|
1383
|
+
* Configuration for REST Comment Adapter
|
|
1384
|
+
*/
|
|
1385
|
+
interface CommentAdapterConfig {
|
|
1386
|
+
/** Base URL for API */
|
|
1387
|
+
baseUrl: string;
|
|
1388
|
+
/** API endpoints */
|
|
1389
|
+
endpoints: CommentEndpoints;
|
|
1390
|
+
/** Custom headers getter */
|
|
1391
|
+
getHeaders?: () => Promise<Record<string, string>> | Record<string, string>;
|
|
1392
|
+
/** Custom params to include in all requests */
|
|
1393
|
+
customParams?: Record<string, string>;
|
|
1394
|
+
/** Response transformers */
|
|
1395
|
+
transformers?: CommentTransformers;
|
|
1396
|
+
}
|
|
1397
|
+
/**
|
|
1398
|
+
* Comment API endpoints configuration
|
|
1399
|
+
*/
|
|
1400
|
+
interface CommentEndpoints {
|
|
1401
|
+
/** Get comments: GET /videos/:videoId/comments */
|
|
1402
|
+
list: string;
|
|
1403
|
+
/** Get replies: GET /comments/:commentId/replies */
|
|
1404
|
+
replies: string;
|
|
1405
|
+
/** Post comment: POST /videos/:videoId/comments */
|
|
1406
|
+
post: string;
|
|
1407
|
+
/** Post reply: POST /comments/:commentId/replies */
|
|
1408
|
+
postReply: string;
|
|
1409
|
+
/** Edit comment: PATCH /comments/:id */
|
|
1410
|
+
edit: string;
|
|
1411
|
+
/** Delete comment: DELETE /comments/:id */
|
|
1412
|
+
delete: string;
|
|
1413
|
+
/** Like comment: POST /comments/:id/like */
|
|
1414
|
+
like: string;
|
|
1415
|
+
/** Unlike comment: DELETE /comments/:id/like */
|
|
1416
|
+
unlike: string;
|
|
1417
|
+
/** Report comment: POST /comments/:id/report */
|
|
1418
|
+
report: string;
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* Default endpoints (RESTful convention)
|
|
1422
|
+
*/
|
|
1423
|
+
declare const DEFAULT_COMMENT_ENDPOINTS: CommentEndpoints;
|
|
1424
|
+
/**
|
|
1425
|
+
* Response transformers for custom API formats
|
|
1426
|
+
*/
|
|
1427
|
+
interface CommentTransformers {
|
|
1428
|
+
/** Transform API response to CommentListResponse */
|
|
1429
|
+
commentList?: (raw: unknown) => CommentListResponse;
|
|
1430
|
+
/** Transform API response to ReplyListResponse */
|
|
1431
|
+
replyList?: (raw: unknown) => ReplyListResponse;
|
|
1432
|
+
/** Transform API response to CommentItem */
|
|
1433
|
+
comment?: (raw: unknown) => CommentItem;
|
|
1434
|
+
/** Transform API response to ReplyItem */
|
|
1435
|
+
reply?: (raw: unknown) => ReplyItem;
|
|
1436
|
+
}
|
|
1437
|
+
/**
|
|
1438
|
+
* Configuration for Mock Comment Adapter (testing/demo)
|
|
1439
|
+
*/
|
|
1440
|
+
interface MockCommentAdapterConfig {
|
|
1441
|
+
/** Simulated delay in ms (default: 500) */
|
|
1442
|
+
delay?: number;
|
|
1443
|
+
/** Initial comments per video */
|
|
1444
|
+
initialComments?: CommentItem[];
|
|
1445
|
+
/** Simulate errors */
|
|
1446
|
+
simulateErrors?: boolean;
|
|
1447
|
+
/** Error rate (0-1, default: 0.1) */
|
|
1448
|
+
errorRate?: number;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
/**
|
|
1452
|
+
* @xhub-short/contracts - Localization Types
|
|
1453
|
+
*
|
|
1454
|
+
* Lightweight i18n support with ICU-like message format.
|
|
1455
|
+
* Custom implementation - NO external dependencies.
|
|
1456
|
+
*
|
|
1457
|
+
* Supported ICU features:
|
|
1458
|
+
* - Simple interpolation: {name}
|
|
1459
|
+
* - Plural: {count, plural, =0 {none} one {# item} other {# items}}
|
|
1460
|
+
* - Select: {key, select, value1 {text1} other {text2}}
|
|
1461
|
+
*/
|
|
1462
|
+
/**
|
|
1463
|
+
* Values that can be interpolated into messages
|
|
1464
|
+
*/
|
|
1465
|
+
type MessageValue = string | number | boolean;
|
|
1466
|
+
/**
|
|
1467
|
+
* Record of values for message interpolation
|
|
1468
|
+
*/
|
|
1469
|
+
type MessageValues = Record<string, MessageValue>;
|
|
1470
|
+
/**
|
|
1471
|
+
* All supported message keys
|
|
1472
|
+
*
|
|
1473
|
+
* Using dot notation for namespacing:
|
|
1474
|
+
* - feed.* : Video feed related
|
|
1475
|
+
* - player.* : Video player related
|
|
1476
|
+
* - comment.* : Comment section related
|
|
1477
|
+
* - action.* : User actions (like, share, follow)
|
|
1478
|
+
* - time.* : Relative time formatting
|
|
1479
|
+
* - number.* : Number formatting suffixes
|
|
1480
|
+
* - error.* : Generic errors
|
|
1481
|
+
*/
|
|
1482
|
+
type MessageKey = 'feed.loading' | 'feed.empty' | 'feed.endReached' | 'feed.error' | 'feed.retry' | 'player.loading' | 'player.error' | 'player.error.network' | 'player.error.decode' | 'player.error.notSupported' | 'player.error.aborted' | 'player.tapToRetry' | 'comment.title' | 'comment.placeholder' | 'comment.empty' | 'comment.loading' | 'comment.error' | 'comment.retry' | 'comment.post' | 'comment.reply' | 'comment.replyTo' | 'comment.viewReplies' | 'comment.hideReplies' | 'comment.loadReplies' | 'comment.viewMoreReplies' | 'comment.delete' | 'comment.report' | 'comment.count' | 'comment.replyCount' | 'comment.expand' | 'comment.collapse' | 'action.like' | 'action.liked' | 'action.comment' | 'action.share' | 'action.bookmark' | 'action.bookmarked' | 'action.follow' | 'action.following' | 'time.now' | 'time.seconds' | 'time.minutes' | 'time.hours' | 'time.days' | 'time.weeks' | 'time.months' | 'time.years' | 'number.thousand' | 'number.million' | 'number.billion' | 'error.generic' | 'error.network' | 'error.timeout' | 'cancel' | 'close' | 'ok' | 'done' | 'aria.loading' | 'aria.videoPlayer' | 'aria.retry' | 'aria.sortComments' | 'aria.closeComments' | 'aria.addMedia' | 'aria.submitComment' | 'aria.openEmoji' | 'aria.cancelReply';
|
|
1483
|
+
/**
|
|
1484
|
+
* Complete message catalog type
|
|
1485
|
+
* All keys must be present
|
|
1486
|
+
*/
|
|
1487
|
+
type MessageCatalog = Record<MessageKey, string>;
|
|
1488
|
+
/**
|
|
1489
|
+
* Partial catalog for overrides
|
|
1490
|
+
*/
|
|
1491
|
+
type PartialMessageCatalog = Partial<MessageCatalog>;
|
|
1492
|
+
/**
|
|
1493
|
+
* Localization Port - Core interface for i18n
|
|
1494
|
+
*
|
|
1495
|
+
* Adapters must implement this interface.
|
|
1496
|
+
* SDK provides default implementation with built-in ICU-like parser.
|
|
1497
|
+
*/
|
|
1498
|
+
interface ILocalization {
|
|
1499
|
+
/**
|
|
1500
|
+
* Current locale (BCP 47 tag, e.g., 'en', 'vi', 'zh-CN')
|
|
1501
|
+
*/
|
|
1502
|
+
readonly locale: string;
|
|
1503
|
+
/**
|
|
1504
|
+
* Translate a message key
|
|
1505
|
+
*
|
|
1506
|
+
* @param key - Message key from catalog
|
|
1507
|
+
* @param values - Optional interpolation values
|
|
1508
|
+
* @returns Translated string
|
|
1509
|
+
*
|
|
1510
|
+
* @example
|
|
1511
|
+
* // Simple
|
|
1512
|
+
* t('feed.loading') // "Loading..."
|
|
1513
|
+
*
|
|
1514
|
+
* // Interpolation
|
|
1515
|
+
* t('comment.replyTo', { name: 'John' }) // "Replying to John"
|
|
1516
|
+
*
|
|
1517
|
+
* // Plural
|
|
1518
|
+
* t('comment.count', { count: 5 }) // "5 comments"
|
|
1519
|
+
*/
|
|
1520
|
+
t(key: MessageKey, values?: MessageValues): string;
|
|
1521
|
+
/**
|
|
1522
|
+
* Format a number with locale-aware separators
|
|
1523
|
+
*
|
|
1524
|
+
* @param value - Number to format
|
|
1525
|
+
* @returns Formatted string (e.g., "1,234" or "1.234")
|
|
1526
|
+
*/
|
|
1527
|
+
formatNumber(value: number): string;
|
|
1528
|
+
/**
|
|
1529
|
+
* Format a number in compact form (1K, 1M, 1B)
|
|
1530
|
+
*
|
|
1531
|
+
* @param value - Number to format
|
|
1532
|
+
* @returns Compact string (e.g., "15K", "1.2M")
|
|
1533
|
+
*/
|
|
1534
|
+
formatCompact(value: number): string;
|
|
1535
|
+
/**
|
|
1536
|
+
* Format relative time (e.g., "2 hours ago")
|
|
1537
|
+
*
|
|
1538
|
+
* @param date - Date or timestamp
|
|
1539
|
+
* @returns Relative time string
|
|
1540
|
+
*/
|
|
1541
|
+
formatRelativeTime(date: Date | number): string;
|
|
1542
|
+
}
|
|
1543
|
+
/**
|
|
1544
|
+
* Localization configuration for SDK
|
|
1545
|
+
*/
|
|
1546
|
+
interface LocalizationConfig {
|
|
1547
|
+
/**
|
|
1548
|
+
* Locale code (BCP 47)
|
|
1549
|
+
* @default 'en'
|
|
1550
|
+
*/
|
|
1551
|
+
locale?: string;
|
|
1552
|
+
/**
|
|
1553
|
+
* Custom messages to override defaults
|
|
1554
|
+
*/
|
|
1555
|
+
messages?: PartialMessageCatalog;
|
|
1556
|
+
/**
|
|
1557
|
+
* Fallback locale when translation not found
|
|
1558
|
+
* @default 'en'
|
|
1559
|
+
*/
|
|
1560
|
+
fallbackLocale?: string;
|
|
1561
|
+
/**
|
|
1562
|
+
* Custom localization adapter (for integration with existing i18n systems)
|
|
1563
|
+
* If provided, SDK will use this instead of built-in implementation
|
|
1564
|
+
*/
|
|
1565
|
+
adapter?: ILocalization;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1046
1568
|
/**
|
|
1047
1569
|
* UI Component Types for XHub-short SDK
|
|
1048
1570
|
*
|
|
@@ -1287,6 +1809,12 @@ interface VideoSlotHeadlessProps {
|
|
|
1287
1809
|
onVisible?: () => void;
|
|
1288
1810
|
/** Called when video becomes hidden */
|
|
1289
1811
|
onHidden?: () => void;
|
|
1812
|
+
/**
|
|
1813
|
+
* Restore frame for session restoration.
|
|
1814
|
+
* Base64 JPEG data URL of the video frame at restore position.
|
|
1815
|
+
* Displayed as instant preview while video loads.
|
|
1816
|
+
*/
|
|
1817
|
+
restoreFrame?: string;
|
|
1290
1818
|
}
|
|
1291
1819
|
/**
|
|
1292
1820
|
* VideoPlayer headless component props
|
|
@@ -1538,6 +2066,189 @@ interface VideoInfoProps extends Omit<VideoInfoHeadlessProps, 'videoInfoState' |
|
|
|
1538
2066
|
/** Called when location is clicked */
|
|
1539
2067
|
onLocationClick?: () => void;
|
|
1540
2068
|
}
|
|
2069
|
+
|
|
2070
|
+
/**
|
|
2071
|
+
* Comment state from useComment() hook
|
|
2072
|
+
*/
|
|
2073
|
+
interface UICommentState {
|
|
2074
|
+
/** Comments for current video */
|
|
2075
|
+
comments: CommentItem[];
|
|
2076
|
+
/** Total comment count */
|
|
2077
|
+
totalCount: number;
|
|
2078
|
+
/** Whether comments are loading */
|
|
2079
|
+
isLoading: boolean;
|
|
2080
|
+
/** Whether more comments are loading */
|
|
2081
|
+
isLoadingMore: boolean;
|
|
2082
|
+
/** Whether there are more comments */
|
|
2083
|
+
hasMore: boolean;
|
|
2084
|
+
/** Error if any */
|
|
2085
|
+
error: Error | null;
|
|
2086
|
+
/** Whether currently posting a comment */
|
|
2087
|
+
isPosting: boolean;
|
|
2088
|
+
/** Config */
|
|
2089
|
+
config: CommentConfig;
|
|
2090
|
+
}
|
|
2091
|
+
/**
|
|
2092
|
+
* Comment actions from useComment() hook
|
|
2093
|
+
*/
|
|
2094
|
+
interface UICommentActions {
|
|
2095
|
+
/** Load comments for a video */
|
|
2096
|
+
loadComments: (videoId: string) => Promise<void>;
|
|
2097
|
+
/** Load more comments */
|
|
2098
|
+
loadMore: () => Promise<void>;
|
|
2099
|
+
/** Post a new comment */
|
|
2100
|
+
postComment: (content: string) => Promise<void>;
|
|
2101
|
+
/** Post a reply */
|
|
2102
|
+
postReply: (parentId: string, content: string, replyTo?: CommentAuthor) => Promise<void>;
|
|
2103
|
+
/** Edit a comment/reply */
|
|
2104
|
+
editComment: (id: string, content: string) => Promise<void>;
|
|
2105
|
+
/** Delete a comment/reply */
|
|
2106
|
+
deleteComment: (id: string, isReply?: boolean, parentId?: string) => Promise<void>;
|
|
2107
|
+
/** Like a comment/reply */
|
|
2108
|
+
likeComment: (id: string) => Promise<void>;
|
|
2109
|
+
/** Unlike a comment/reply */
|
|
2110
|
+
unlikeComment: (id: string) => Promise<void>;
|
|
2111
|
+
/** Load replies for a comment */
|
|
2112
|
+
loadReplies: (commentId: string) => Promise<void>;
|
|
2113
|
+
/** Report a comment */
|
|
2114
|
+
reportComment: (id: string, reason: string) => Promise<void>;
|
|
2115
|
+
/** Refresh comments */
|
|
2116
|
+
refresh: () => Promise<void>;
|
|
2117
|
+
}
|
|
2118
|
+
/**
|
|
2119
|
+
* Comment sheet headless component props
|
|
2120
|
+
*/
|
|
2121
|
+
interface CommentSheetHeadlessProps {
|
|
2122
|
+
/** Comment state */
|
|
2123
|
+
commentState: UICommentState;
|
|
2124
|
+
/** Comment actions */
|
|
2125
|
+
commentActions: UICommentActions;
|
|
2126
|
+
/** Video ID for comments */
|
|
2127
|
+
videoId: string;
|
|
2128
|
+
/** Whether sheet is open */
|
|
2129
|
+
isOpen: boolean;
|
|
2130
|
+
/** Close handler */
|
|
2131
|
+
onClose: () => void;
|
|
2132
|
+
/** Current user for posting (optional - show input only if provided) */
|
|
2133
|
+
currentUser?: CommentAuthor;
|
|
2134
|
+
/** Sheet height as percentage (0-1, default: 0.65) */
|
|
2135
|
+
sheetHeight?: number;
|
|
2136
|
+
/** Animation duration in ms (default: 300) */
|
|
2137
|
+
animationDuration?: number;
|
|
2138
|
+
/** Emoji bar config (optional) */
|
|
2139
|
+
emojiBar?: {
|
|
2140
|
+
enabled?: boolean;
|
|
2141
|
+
emojis?: string[];
|
|
2142
|
+
};
|
|
2143
|
+
/** Custom header content */
|
|
2144
|
+
headerContent?: UINode;
|
|
2145
|
+
/** Custom empty state */
|
|
2146
|
+
emptyContent?: UINode;
|
|
2147
|
+
/** Custom loading state */
|
|
2148
|
+
loadingContent?: UINode;
|
|
2149
|
+
/** Custom error state */
|
|
2150
|
+
errorContent?: UINode;
|
|
2151
|
+
/** Additional class name */
|
|
2152
|
+
className?: string;
|
|
2153
|
+
/** Children (compound components) */
|
|
2154
|
+
children?: UINode;
|
|
2155
|
+
/** Test ID */
|
|
2156
|
+
testId?: string;
|
|
2157
|
+
}
|
|
2158
|
+
/**
|
|
2159
|
+
* Comment sheet wired component props
|
|
2160
|
+
*/
|
|
2161
|
+
interface CommentSheetProps extends Omit<CommentSheetHeadlessProps, 'commentState' | 'commentActions'> {
|
|
2162
|
+
/** Override comment state (optional) */
|
|
2163
|
+
commentState?: UICommentState;
|
|
2164
|
+
/** Override comment actions (optional) */
|
|
2165
|
+
commentActions?: UICommentActions;
|
|
2166
|
+
/** Video playback behavior when sheet opens */
|
|
2167
|
+
onOpenBehavior?: 'pause' | 'mute' | 'continue';
|
|
2168
|
+
/** Video animation config */
|
|
2169
|
+
videoAnimation?: {
|
|
2170
|
+
/** Enable video shrink animation (default: true) */
|
|
2171
|
+
enabled?: boolean;
|
|
2172
|
+
/** Animation duration in ms (default: 300) */
|
|
2173
|
+
duration?: number;
|
|
2174
|
+
/** Video behavior: 'shrink' | 'dim' | 'none' (default: 'shrink') */
|
|
2175
|
+
behavior?: 'shrink' | 'dim' | 'none';
|
|
2176
|
+
};
|
|
2177
|
+
/** Callback when input is focused (for Flutter bridge) */
|
|
2178
|
+
onInputFocus?: () => void;
|
|
2179
|
+
/** Callback when input is blurred */
|
|
2180
|
+
onInputBlur?: () => void;
|
|
2181
|
+
}
|
|
2182
|
+
/**
|
|
2183
|
+
* Comment item headless component props
|
|
2184
|
+
*/
|
|
2185
|
+
interface CommentItemHeadlessProps {
|
|
2186
|
+
/** Comment data */
|
|
2187
|
+
comment: CommentItem;
|
|
2188
|
+
/** Comment actions */
|
|
2189
|
+
actions: UICommentActions;
|
|
2190
|
+
/** Config */
|
|
2191
|
+
config: CommentConfig;
|
|
2192
|
+
/** Whether to show replies section */
|
|
2193
|
+
showReplies?: boolean;
|
|
2194
|
+
/** Whether replies are expanded */
|
|
2195
|
+
repliesExpanded?: boolean;
|
|
2196
|
+
/** Toggle replies expansion */
|
|
2197
|
+
onToggleReplies?: () => void;
|
|
2198
|
+
/** Current user (for reply input) */
|
|
2199
|
+
currentUser?: CommentAuthor;
|
|
2200
|
+
/** Additional class name */
|
|
2201
|
+
className?: string;
|
|
2202
|
+
/** Test ID */
|
|
2203
|
+
testId?: string;
|
|
2204
|
+
}
|
|
2205
|
+
/**
|
|
2206
|
+
* Reply item headless component props
|
|
2207
|
+
*/
|
|
2208
|
+
interface ReplyItemHeadlessProps {
|
|
2209
|
+
/** Reply data */
|
|
2210
|
+
reply: ReplyItem;
|
|
2211
|
+
/** Parent comment */
|
|
2212
|
+
parentComment: CommentItem;
|
|
2213
|
+
/** Comment actions */
|
|
2214
|
+
actions: UICommentActions;
|
|
2215
|
+
/** Config */
|
|
2216
|
+
config: CommentConfig;
|
|
2217
|
+
/** Additional class name */
|
|
2218
|
+
className?: string;
|
|
2219
|
+
/** Test ID */
|
|
2220
|
+
testId?: string;
|
|
2221
|
+
}
|
|
2222
|
+
/**
|
|
2223
|
+
* Comment input headless component props
|
|
2224
|
+
*/
|
|
2225
|
+
interface CommentInputHeadlessProps {
|
|
2226
|
+
/** Current user */
|
|
2227
|
+
currentUser: CommentAuthor;
|
|
2228
|
+
/** Submit handler */
|
|
2229
|
+
onSubmit: (content: string) => Promise<void>;
|
|
2230
|
+
/** Whether submitting */
|
|
2231
|
+
isSubmitting?: boolean;
|
|
2232
|
+
/** Placeholder text */
|
|
2233
|
+
placeholder?: string;
|
|
2234
|
+
/** Reply to user (shows @mention) */
|
|
2235
|
+
replyTo?: CommentAuthor;
|
|
2236
|
+
/** Clear reply target */
|
|
2237
|
+
onClearReply?: () => void;
|
|
2238
|
+
/** Emoji bar config */
|
|
2239
|
+
emojiBar?: {
|
|
2240
|
+
enabled?: boolean;
|
|
2241
|
+
emojis?: string[];
|
|
2242
|
+
};
|
|
2243
|
+
/** Input focus handler */
|
|
2244
|
+
onFocus?: () => void;
|
|
2245
|
+
/** Input blur handler */
|
|
2246
|
+
onBlur?: () => void;
|
|
2247
|
+
/** Additional class name */
|
|
2248
|
+
className?: string;
|
|
2249
|
+
/** Test ID */
|
|
2250
|
+
testId?: string;
|
|
2251
|
+
}
|
|
1541
2252
|
/**
|
|
1542
2253
|
* Hook configuration for HOC factory
|
|
1543
2254
|
*/
|
|
@@ -1563,4 +2274,4 @@ type IconComponent = UIComponent<{
|
|
|
1563
2274
|
*/
|
|
1564
2275
|
type FormatCountFn = (count: number) => string;
|
|
1565
2276
|
|
|
1566
|
-
export type
|
|
2277
|
+
export { type ActionBarHeadlessProps, type ActionBarProps, type ActionButtonHeadlessProps, type AnalyticsConfig, type AnalyticsEvent, type AnalyticsEventType, type Author, type AuthorInfoHeadlessProps, type AuthorInfoProps, type Comment, type CommentAdapterConfig, type CommentAuthor, type CommentConfig, type CommentEndpoints, type CommentInputHeadlessProps, type CommentItem, type CommentItemHeadlessProps, type CommentListResponse, type CommentManagerState, type CommentReportReason, type CommentSheetHeadlessProps, type CommentSheetProps, type CommentState, type CommentTransformers, DEFAULT_COMMENT_CONFIG, DEFAULT_COMMENT_ENDPOINTS, type DeleteCommentPayload, type EditCommentPayload, type ErrorBoundaryProps, type FeedResponse, type FeedState, type FormatCountFn, type IAnalytics, type ICommentAdapter, type IDataSource, type IInteraction, type ILocalization, type ILogger, type INetworkAdapter, type IPosterLoader, type ISessionStorage, type IStorage, type IVideoLoader, type IconComponent, type InternalLogger, type LocalizationConfig, type LogEntry, type LogLevel, type LoggerConfig, type MessageCatalog, type MessageKey, type MessageValue, type MessageValues, type MockCommentAdapterConfig, type MusicInfo, type NetworkQuality, type NetworkType, type OptimisticAction, type PartialMessageCatalog, type PlaybackState, type PlayerError, type PlayerState, type PostCommentPayload, type PostReplyPayload, type PrefetchCacheData, type PreloadConfig, type PreloadResult, type PreloadStatus, type ProgressBarHeadlessProps, type ReplyItem, type ReplyItemHeadlessProps, type ReplyListResponse, type ReportCommentPayload, type SDKConfig, type SessionSnapshot, type SkeletonProps, type UIAuthorActions, type UIAuthorState, type UICommentActions, type UICommentState, type UIComponent, type UIFeedState, type UIInteractionActions, type UIInteractionState, type UINode, type UIPlayerControls, type UIPlayerState, type UIRef, type UIResourceState, type UISwipeState, type UIVideoInfoActions, type UIVideoInfoState, type VideoFeedHeadlessProps, type VideoFeedProps, type VideoInfoHeadlessProps, type VideoInfoProps, type VideoItem, type VideoPlayerHeadlessProps, type VideoPlayerWiredProps, type VideoQuality, type VideoSlotHeadlessProps, type VideoSlotProps, type VideoSource, type VideoStats, type WiredComponent, type WiredComponentConfig };
|
package/dist/index.js
CHANGED
|
@@ -1 +1,28 @@
|
|
|
1
|
+
// src/comment-types.ts
|
|
2
|
+
var DEFAULT_COMMENT_CONFIG = {
|
|
3
|
+
pageSize: 20,
|
|
4
|
+
replyPageSize: 10,
|
|
5
|
+
cacheTTL: 5 * 60 * 1e3,
|
|
6
|
+
// 5 minutes
|
|
7
|
+
repliesAutoExpandThreshold: 1,
|
|
8
|
+
repliesCollapseLimit: 3,
|
|
9
|
+
textMaxLines: 3,
|
|
10
|
+
inputMaxLength: 500,
|
|
11
|
+
enableOptimisticUI: true,
|
|
12
|
+
requireDeleteConfirm: true
|
|
13
|
+
};
|
|
1
14
|
|
|
15
|
+
// src/comment-adapter.ts
|
|
16
|
+
var DEFAULT_COMMENT_ENDPOINTS = {
|
|
17
|
+
list: "/videos/:videoId/comments",
|
|
18
|
+
replies: "/comments/:commentId/replies",
|
|
19
|
+
post: "/videos/:videoId/comments",
|
|
20
|
+
postReply: "/comments/:commentId/replies",
|
|
21
|
+
edit: "/comments/:id",
|
|
22
|
+
delete: "/comments/:id",
|
|
23
|
+
like: "/comments/:id/like",
|
|
24
|
+
unlike: "/comments/:id/like",
|
|
25
|
+
report: "/comments/:id/report"
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { DEFAULT_COMMENT_CONFIG, DEFAULT_COMMENT_ENDPOINTS };
|