@xhub-short/sdk 0.1.0-beta.0
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 +596 -0
- package/dist/index.d.ts +1601 -0
- package/dist/index.js +1759 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
# @xhub-short/sdk
|
|
2
|
+
|
|
3
|
+
> **Glue Layer** - KαΊΏt nα»i Core Domain vα»i React UI
|
|
4
|
+
|
|
5
|
+
## π SDK lΓ gΓ¬?
|
|
6
|
+
|
|
7
|
+
**SDK (Software Development Kit)** lΓ package chΓnh mΓ Host App cΓ i ΔαΊ·t Δα» tΓch hợp Short Video Feed. NΓ³ ΔΓ³ng vai trΓ² **"Glue Layer"** - kαΊΏt nα»i tαΊ₯t cαΊ£ cΓ‘c thΓ nh phαΊ§n bΓͺn trong SDK thΓ nh mα»t API thα»ng nhαΊ₯t, dα»
sα» dα»₯ng.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
11
|
+
β HOST APP (Your App) β
|
|
12
|
+
β β
|
|
13
|
+
β import { ShortVideoProvider, useFeed, usePlayer } from '@xhub-short/sdk';
|
|
14
|
+
β import { VideoFeed, VideoPlayer } from '@xhub-short/ui'; β
|
|
15
|
+
β β
|
|
16
|
+
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
|
|
17
|
+
β uses
|
|
18
|
+
βΌ
|
|
19
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
20
|
+
β @xhub-short/ui β
|
|
21
|
+
β (Lego Components - Phase 4) β
|
|
22
|
+
β β
|
|
23
|
+
β VideoFeed, VideoPlayer, InteractionBar, CommentSheet... β
|
|
24
|
+
β β
|
|
25
|
+
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
|
|
26
|
+
β imports hooks from
|
|
27
|
+
βΌ
|
|
28
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
29
|
+
β @xhub-short/sdk β
|
|
30
|
+
β (Glue Layer - Current) β
|
|
31
|
+
β β
|
|
32
|
+
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
|
|
33
|
+
β β Provider β β Hooks β β Factory (createSDK) β β
|
|
34
|
+
β β (Context) β β (React) β β (Dependency Inject) β β
|
|
35
|
+
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
|
|
36
|
+
β β
|
|
37
|
+
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββ
|
|
38
|
+
β orchestrates
|
|
39
|
+
ββββββββββββββββββββββ΄βββββββββββββββββββββ
|
|
40
|
+
βΌ βΌ
|
|
41
|
+
βββββββββββββββ βββββββββββββββ
|
|
42
|
+
β @core β β @adapters β
|
|
43
|
+
β (Domain) β β (Infra) β
|
|
44
|
+
βββββββββββββββ βββββββββββββββ
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
> **LΖ°u Γ½:** `@sdk` **KHΓNG** import tα»« `@ui`. MΕ©i tΓͺn chα» hΖ°α»ng dependency (ai import ai).
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## π― TαΊ‘i sao cαΊ§n SDK?
|
|
52
|
+
|
|
53
|
+
| VαΊ₯n Δα» | GiαΊ£i phΓ‘p cα»§a SDK |
|
|
54
|
+
|--------|-------------------|
|
|
55
|
+
| Host App phαΊ£i hiα»u kiαΊΏn trΓΊc phα»©c tαΊ‘p bΓͺn trong | SDK expose API ΔΖ‘n giαΊ£n: hooks + provider |
|
|
56
|
+
| KhΓ³ setup dependency injection cho adapters | `createSDK()` tα»± Δα»ng wire tαΊ₯t cαΊ£ |
|
|
57
|
+
| State management phα»©c tαΊ‘p (Feed, Player, Resource...) | Hooks abstract hαΊΏt complexity |
|
|
58
|
+
| SSR compatibility | `useSyncExternalStore` built-in |
|
|
59
|
+
| Memory leaks khi unmount | `sdk.destroy()` cleanup tα»± Δα»ng |
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## π Nhiα»m vα»₯ chi tiαΊΏt cα»§a SDK
|
|
64
|
+
|
|
65
|
+
SDK thα»±c hiα»n **7 nhiα»m vα»₯ chΓnh** Δα» Host App cΓ³ thα» tΓch hợp dα»
dΓ ng:
|
|
66
|
+
|
|
67
|
+
### 1. Dependency Injection & Wiring
|
|
68
|
+
|
|
69
|
+
SDK lΓ nΖ‘i **duy nhαΊ₯t** thα»±c hiα»n dependency injection - kαΊΏt nα»i cΓ‘c adapters vα»i core managers:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
73
|
+
β DEPENDENCY INJECTION MAP β
|
|
74
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
75
|
+
β β
|
|
76
|
+
β Adapter Interface ββββΊ Core Component β
|
|
77
|
+
β βββββββββββββββββ ββββββββββββββ β
|
|
78
|
+
β IDataSource ββββΊ FeedManager β
|
|
79
|
+
β IInteraction ββββΊ OptimisticManager β
|
|
80
|
+
β ISessionStorage ββββΊ LifecycleManager β
|
|
81
|
+
β INetworkAdapter ββββΊ ResourceGovernor β
|
|
82
|
+
β IVideoLoader + IPosterLoader ββββΊ ResourceGovernor β
|
|
83
|
+
β IAnalytics ββββΊ PlayerEngine (events) β
|
|
84
|
+
β ILogger ββββΊ All managers (debug) β
|
|
85
|
+
β β
|
|
86
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 2. Adapter Resolution
|
|
90
|
+
|
|
91
|
+
SDK tα»± Δα»ng resolve adapters theo thα»© tα»± Ζ°u tiΓͺn:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
Config Priority:
|
|
95
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
96
|
+
β β
|
|
97
|
+
β 1. config.adapters.dataSource βββ Highest (User-defined)β
|
|
98
|
+
β β β
|
|
99
|
+
β βΌ fallback β
|
|
100
|
+
β 2. config.preset β createBrowserAdapters() β
|
|
101
|
+
β β β
|
|
102
|
+
β βΌ fallback β
|
|
103
|
+
β 3. MockAdapter βββ Lowest (Development) β
|
|
104
|
+
β β
|
|
105
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Δiα»u nΓ y cho phΓ©p:
|
|
109
|
+
- **Development**: KhΓ΄ng cαΊ§n config β Mock adapters tα»± Δα»ng
|
|
110
|
+
- **Production vα»i Preset**: Chα» cαΊ§n `baseUrl + auth + endpoints`
|
|
111
|
+
- **Full Custom**: Override bαΊ₯t kα»³ adapter nΓ o
|
|
112
|
+
|
|
113
|
+
### 3. State Synchronization (Core β React)
|
|
114
|
+
|
|
115
|
+
Core Domain sα» dα»₯ng **vanilla stores** (khΓ΄ng React). SDK bridge chΓΊng sang React:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
|
|
119
|
+
β Core Store β β SDK Hook β β React UI β
|
|
120
|
+
β (Vanilla) β ββββΊ β (useSyncExternalβ ββββΊ β (Re-render) β
|
|
121
|
+
β β β Store) β β β
|
|
122
|
+
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
|
|
123
|
+
β β
|
|
124
|
+
β store.subscribe() β getSnapshot()
|
|
125
|
+
β store.setState() β
|
|
126
|
+
βΌ βΌ
|
|
127
|
+
Framework-agnostic SSR-safe subscription
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**TαΊ‘i sao khΓ΄ng dΓΉng Zustand trα»±c tiαΊΏp trong Core?**
|
|
131
|
+
- Core phαΊ£i framework-agnostic (cΓ³ thα» dΓΉng vα»i Vue, Svelte...)
|
|
132
|
+
- GiαΊ£m bundle size cho Core package
|
|
133
|
+
- TΓ‘ch biα»t concerns rΓ΅ rΓ ng
|
|
134
|
+
|
|
135
|
+
### 4. Event Orchestration
|
|
136
|
+
|
|
137
|
+
SDK wire cΓ‘c events giα»―a managers Δα» chΓΊng phα»i hợp:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
141
|
+
β EVENT WIRING β
|
|
142
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
143
|
+
β β
|
|
144
|
+
β PlayerEngine β
|
|
145
|
+
β β β
|
|
146
|
+
β βββ on('videoChange') βββββββΊ Analytics.flush() β
|
|
147
|
+
β β (Flush trΖ°α»c khi Δα»i video) β
|
|
148
|
+
β β β
|
|
149
|
+
β βββ on('timeUpdate') ββββββββΊ LifecycleManager.setPendingSave()β
|
|
150
|
+
β (Auto-save playback position) β
|
|
151
|
+
β β
|
|
152
|
+
β LifecycleManager β
|
|
153
|
+
β β β
|
|
154
|
+
β βββ on('visibilityChange') ββΊ Analytics.flush() β
|
|
155
|
+
β (state === 'hidden') (Flush khi app background) β
|
|
156
|
+
β β
|
|
157
|
+
β ResourceGovernor β
|
|
158
|
+
β β β
|
|
159
|
+
β βββ on('focusChange') βββββββΊ PlayerEngine.load(video) β
|
|
160
|
+
β (Load video khi swipe) β
|
|
161
|
+
β β
|
|
162
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### 5. Lifecycle Management
|
|
166
|
+
|
|
167
|
+
SDK quαΊ£n lΓ½ toΓ n bα» vΓ²ng Δα»i cα»§a cΓ‘c managers:
|
|
168
|
+
|
|
169
|
+
| Phase | SDK Actions |
|
|
170
|
+
|-------|-------------|
|
|
171
|
+
| **Init** | TαΊ‘o managers, inject adapters, wire events, restore session |
|
|
172
|
+
| **Active** | Managers hoαΊ‘t Δα»ng Δα»c lαΊp, SDK chα» expose hooks |
|
|
173
|
+
| **Background** | Auto-save session, flush analytics |
|
|
174
|
+
| **Destroy** | Cleanup timers, unsubscribe events, clear cache |
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// Tα»± Δα»ng trong Provider:
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
const sdk = createSDK(config);
|
|
180
|
+
return () => sdk.destroy(); // Cleanup khi unmount
|
|
181
|
+
}, []);
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 6. Public API Surface
|
|
185
|
+
|
|
186
|
+
SDK expose API ΔΖ‘n giαΊ£n, αΊ©n Δi complexity bΓͺn trong:
|
|
187
|
+
|
|
188
|
+
| Exposed to Host App | Hidden from Host App |
|
|
189
|
+
|---------------------|----------------------|
|
|
190
|
+
| `useFeed()` - videos, loadMore | FeedManager internals |
|
|
191
|
+
| `usePlayer()` - play, pause, seek | PlayerEngine state machine |
|
|
192
|
+
| `useOptimistic()` - like, follow | Rollback queue, pending states |
|
|
193
|
+
| `useSwipeGesture()` - onSwipe | DOM allocation logic |
|
|
194
|
+
| Config vα»i preset | Adapter creation |
|
|
195
|
+
|
|
196
|
+
### 7. SSR Support
|
|
197
|
+
|
|
198
|
+
SDK ΔαΊ£m bαΊ£o hoαΊ‘t Δα»ng vα»i Server-Side Rendering:
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
202
|
+
β SSR STRATEGY β
|
|
203
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
204
|
+
β β
|
|
205
|
+
β Server: β
|
|
206
|
+
β ββ ShortVideoProvider renders vα»i empty state β
|
|
207
|
+
β ββ Hooks return initial/fallback values β
|
|
208
|
+
β ββ KhΓ΄ng tαΊ‘o SDK instance β
|
|
209
|
+
β β
|
|
210
|
+
β Client (Hydration): β
|
|
211
|
+
β ββ useEffect tαΊ‘o SDK instance β
|
|
212
|
+
β ββ Restore session tα»« localStorage β
|
|
213
|
+
β ββ useSyncExternalStore subscribe to stores β
|
|
214
|
+
β β
|
|
215
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## ποΈ KiαΊΏn trΓΊc
|
|
221
|
+
|
|
222
|
+
### Vα» trΓ trong hα» thα»ng
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
226
|
+
β HEXAGONAL ARCHITECTURE β
|
|
227
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
228
|
+
β β
|
|
229
|
+
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
230
|
+
β β @xhub-short/sdk β β
|
|
231
|
+
β β ββββββββββββββββ β β
|
|
232
|
+
β β β β
|
|
233
|
+
β β ShortVideoProvider βββββββ¬ββββββββ createSDK() β β
|
|
234
|
+
β β β β β β β
|
|
235
|
+
β β β Dependency Injection β β β
|
|
236
|
+
β β β β β β β
|
|
237
|
+
β β βΌ βΌ βΌ β β
|
|
238
|
+
β β ββββββββββββ ββββββββββββ ββββββββββββ β β
|
|
239
|
+
β β β Hooks β β Core β β Adapters β β β
|
|
240
|
+
β β β (React) βββββββΆβ Managers βββββ (Inject) β β β
|
|
241
|
+
β β ββββββββββββ ββββββββββββ ββββββββββββ β β
|
|
242
|
+
β β β β
|
|
243
|
+
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
|
|
244
|
+
β β
|
|
245
|
+
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββββββββββ β
|
|
246
|
+
β β @contracts β β @core β β @adapters β β
|
|
247
|
+
β β (Interfaces) β β (Domain) β β (Infrastructure) β β
|
|
248
|
+
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββββββββββ β
|
|
249
|
+
β β
|
|
250
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Package Dependencies
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
@xhub-short/sdk
|
|
257
|
+
βββ @xhub-short/contracts (types, interfaces)
|
|
258
|
+
βββ @xhub-short/core (domain logic)
|
|
259
|
+
βββ @xhub-short/adapters (mock + preset adapters)
|
|
260
|
+
βββ react (peer dependency)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## β¨ Chα»©c nΔng chΓnh
|
|
266
|
+
|
|
267
|
+
### 1. **Provider** - Context cho toΓ n bα» SDK
|
|
268
|
+
|
|
269
|
+
```tsx
|
|
270
|
+
<ShortVideoProvider config={{ preset: {...} }}>
|
|
271
|
+
<YourApp />
|
|
272
|
+
</ShortVideoProvider>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### 2. **Hooks** - React API Δα» truy cαΊp SDK
|
|
276
|
+
|
|
277
|
+
| Hook | Mα»₯c ΔΓch |
|
|
278
|
+
|------|----------|
|
|
279
|
+
| `useFeed()` | Video list, pagination, loading states |
|
|
280
|
+
| `usePlayer()` | Playback control, time, volume, handlers |
|
|
281
|
+
| `useResource()` | DOM allocations, prefetch queue |
|
|
282
|
+
| `useOptimistic()` | Like/Follow vα»i instant UI + rollback |
|
|
283
|
+
| `useSwipeGesture()` | Vertical swipe navigation |
|
|
284
|
+
|
|
285
|
+
### 3. **Wired Components** - Pre-connected UI Components
|
|
286
|
+
|
|
287
|
+
SDK exports pre-wired versions of UI components with SDK hooks already injected:
|
|
288
|
+
|
|
289
|
+
| Component | Description |
|
|
290
|
+
|-----------|-------------|
|
|
291
|
+
| `VideoFeed` | Wired VideoFeedHeadless with useFeed + useSwipeGesture |
|
|
292
|
+
| `VideoSlot` | Wired VideoSlotHeadless with useResourceAllocation + usePlayer |
|
|
293
|
+
| `VideoPlayer` | Wired VideoPlayerHeadless with usePlayer (auto-load, sync) |
|
|
294
|
+
| `ProgressBar` | Wired progress bar with Direct DOM Update (60fps smooth) |
|
|
295
|
+
|
|
296
|
+
#### VideoPlayer (Wired)
|
|
297
|
+
|
|
298
|
+
Pre-wired video player that auto-connects to SDK PlayerEngine.
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
import { VideoSlot, VideoPlayer } from '@xhub-short/sdk';
|
|
302
|
+
import { VideoSlotPoster, VideoSlotOverlay } from '@xhub-short/ui';
|
|
303
|
+
|
|
304
|
+
function FeedItem({ video }) {
|
|
305
|
+
return (
|
|
306
|
+
<VideoSlot video={video}>
|
|
307
|
+
<VideoPlayer
|
|
308
|
+
resetOnInactive={true} // TikTok-like: restart from beginning
|
|
309
|
+
/>
|
|
310
|
+
<VideoSlotPoster />
|
|
311
|
+
<VideoSlotOverlay>...</VideoSlotOverlay>
|
|
312
|
+
</VideoSlot>
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
| Prop | Type | Default | Description |
|
|
318
|
+
|------|------|---------|-------------|
|
|
319
|
+
| `video` | `VideoItem` | from context | Video to play (optional if inside VideoSlot) |
|
|
320
|
+
| `autoLoad` | `boolean` | `true` | Auto-load video into PlayerEngine |
|
|
321
|
+
| `autoPlay` | `boolean` | `true` | Auto-play when slot becomes active |
|
|
322
|
+
| `resetOnInactive` | `boolean` | `true` | Reset video to 0:00 when slot becomes inactive |
|
|
323
|
+
| `loop` | `boolean` | `true` | Loop video playback |
|
|
324
|
+
| `muted` | `boolean` | `true` | Start muted (required for autoplay) |
|
|
325
|
+
|
|
326
|
+
**`resetOnInactive` behavior:**
|
|
327
|
+
- `true` (default): TikTok-like - swiping back restarts video from beginning
|
|
328
|
+
- `false`: YouTube-like - video continues from where user left off
|
|
329
|
+
|
|
330
|
+
#### ProgressBar (Wired) - P11 Re-render Optimization
|
|
331
|
+
|
|
332
|
+
Pre-wired progress bar that uses **Direct DOM Update** for 60fps smooth animation.
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
import { VideoSlot, VideoPlayer, ProgressBar } from '@xhub-short/sdk';
|
|
336
|
+
import { VideoSlotOverlay } from '@xhub-short/ui';
|
|
337
|
+
|
|
338
|
+
function FeedItem({ video }) {
|
|
339
|
+
return (
|
|
340
|
+
<VideoSlot video={video}>
|
|
341
|
+
<VideoPlayer />
|
|
342
|
+
<VideoSlotOverlay>
|
|
343
|
+
<ProgressBar seekable={true} /> {/* 60fps smooth! */}
|
|
344
|
+
</VideoSlotOverlay>
|
|
345
|
+
</VideoSlot>
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
| Prop | Type | Default | Description |
|
|
351
|
+
|------|------|---------|-------------|
|
|
352
|
+
| `seekable` | `boolean` | `true` | Enable click/drag to seek |
|
|
353
|
+
| `showTime` | `boolean` | `false` | Show current/duration text |
|
|
354
|
+
| `showTooltip` | `boolean` | `true` | Show tooltip on hover |
|
|
355
|
+
| `minimal` | `boolean` | `false` | Thin bar without handle |
|
|
356
|
+
|
|
357
|
+
**Performance Architecture:**
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
PlayerEngine.store βββββ subscribe() βββββ fillRef.style.transform
|
|
361
|
+
(scaleX, GPU accelerated)
|
|
362
|
+
NOT React re-render!
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
This component demonstrates ADR 005: Direct DOM Manipulation for high-frequency updates.
|
|
366
|
+
See `docs/issues/RE_RENDER_ANALYSIS.md` for detailed optimization rationale.
|
|
367
|
+
|
|
368
|
+
### 4. **Factory** - Dependency Injection
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
const sdk = createSDK({
|
|
372
|
+
preset: { baseUrl, auth, endpoints }, // Auto-generate adapters
|
|
373
|
+
adapters: { dataSource, interaction }, // Or custom adapters
|
|
374
|
+
feed: { pageSize: 20 },
|
|
375
|
+
player: { autoplay: true },
|
|
376
|
+
});
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## π CΓ‘ch hoαΊ‘t Δα»ng
|
|
382
|
+
|
|
383
|
+
### Flow: Tα»« Config ΔαΊΏn UI
|
|
384
|
+
|
|
385
|
+
```
|
|
386
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
387
|
+
β INITIALIZATION β
|
|
388
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
389
|
+
β β
|
|
390
|
+
β 1. Host App mount <ShortVideoProvider config={...}> β
|
|
391
|
+
β β β
|
|
392
|
+
β βΌ β
|
|
393
|
+
β 2. createSDK(config) β
|
|
394
|
+
β ββ Resolve adapters (preset β browser adapters) β
|
|
395
|
+
β ββ Create Core managers: β
|
|
396
|
+
β β ββ FeedManager (video list, deduplication, GC) β
|
|
397
|
+
β β ββ PlayerEngine (playback state machine) β
|
|
398
|
+
β β ββ ResourceGovernor (DOM allocation, prefetch) β
|
|
399
|
+
β β ββ OptimisticManager (like/follow with rollback) β
|
|
400
|
+
β β ββ LifecycleManager (session persistence) β
|
|
401
|
+
β ββ Wire analytics flush events β
|
|
402
|
+
β β β
|
|
403
|
+
β βΌ β
|
|
404
|
+
β 3. SDKContext.Provider value={sdk} β
|
|
405
|
+
β β β
|
|
406
|
+
β βΌ β
|
|
407
|
+
β 4. Hooks subscribe to managers via useSyncExternalStore β
|
|
408
|
+
β β
|
|
409
|
+
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Flow: User Interaction
|
|
413
|
+
|
|
414
|
+
```
|
|
415
|
+
User swipes down
|
|
416
|
+
β
|
|
417
|
+
βΌ
|
|
418
|
+
useSwipeGesture() ββββββββββΊ ResourceGovernor.setFocusedIndex(n+1)
|
|
419
|
+
β
|
|
420
|
+
ββββββββββββββββββΌβββββββββββββββββ
|
|
421
|
+
βΌ βΌ βΌ
|
|
422
|
+
Deallocate Allocate Preload
|
|
423
|
+
video[n-1] video[n+1] video[n+2]
|
|
424
|
+
β
|
|
425
|
+
βΌ
|
|
426
|
+
PlayerEngine.load(video)
|
|
427
|
+
β
|
|
428
|
+
βΌ
|
|
429
|
+
Analytics.track('video_view')
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## π¦ Exports
|
|
435
|
+
|
|
436
|
+
### Provider
|
|
437
|
+
|
|
438
|
+
```typescript
|
|
439
|
+
export { ShortVideoProvider } from './provider';
|
|
440
|
+
export type { ShortVideoProviderProps, SDKConfig } from './provider';
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Hooks
|
|
444
|
+
|
|
445
|
+
```typescript
|
|
446
|
+
// Feed management
|
|
447
|
+
export { useFeed, useFeedSelector } from './hooks';
|
|
448
|
+
|
|
449
|
+
// Player control
|
|
450
|
+
export { usePlayer, usePlayerSelector, usePlayerForVideo } from './hooks';
|
|
451
|
+
|
|
452
|
+
// Resource management (DOM allocation)
|
|
453
|
+
export { useResource, useResourceSelector, useResourceAllocation } from './hooks';
|
|
454
|
+
|
|
455
|
+
// Optimistic UI (like/follow)
|
|
456
|
+
export { useOptimistic, useOptimisticSelector } from './hooks';
|
|
457
|
+
|
|
458
|
+
// Swipe navigation
|
|
459
|
+
export { useSwipeGesture } from './hooks';
|
|
460
|
+
|
|
461
|
+
// SDK context access
|
|
462
|
+
export { useSDK } from './hooks';
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Factory
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
export { createSDK } from './store';
|
|
469
|
+
export type { SDKInstance } from './store';
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Types (Re-exported)
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
// From @xhub-short/contracts
|
|
476
|
+
export type { VideoItem, FeedResponse, IDataSource, ... } from '@xhub-short/contracts';
|
|
477
|
+
|
|
478
|
+
// From @xhub-short/core
|
|
479
|
+
export type { FeedState, PlayerState, ResourceState, ... } from '@xhub-short/core';
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## π Quick Start
|
|
485
|
+
|
|
486
|
+
### Basic Usage
|
|
487
|
+
|
|
488
|
+
```tsx
|
|
489
|
+
import { ShortVideoProvider, useFeed, usePlayer } from '@xhub-short/sdk';
|
|
490
|
+
|
|
491
|
+
function App() {
|
|
492
|
+
return (
|
|
493
|
+
<ShortVideoProvider
|
|
494
|
+
config={{
|
|
495
|
+
preset: {
|
|
496
|
+
baseUrl: 'https://api.example.com/v1',
|
|
497
|
+
auth: { getAccessToken: () => localStorage.getItem('token') },
|
|
498
|
+
endpoints: {
|
|
499
|
+
feed: { list: '/videos', detail: '/videos/:id' },
|
|
500
|
+
interaction: { like: '/videos/:id/like', ... },
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
}}
|
|
504
|
+
>
|
|
505
|
+
<VideoFeed />
|
|
506
|
+
</ShortVideoProvider>
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function VideoFeed() {
|
|
511
|
+
const { videos, loadInitial, loadMore, hasMore } = useFeed();
|
|
512
|
+
const { load, play, pause, isPlaying } = usePlayer();
|
|
513
|
+
|
|
514
|
+
// Your UI here...
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### With Custom Adapters
|
|
519
|
+
|
|
520
|
+
```tsx
|
|
521
|
+
<ShortVideoProvider
|
|
522
|
+
config={{
|
|
523
|
+
adapters: {
|
|
524
|
+
dataSource: new MyGraphQLAdapter(),
|
|
525
|
+
interaction: new MyFlutterBridgeAdapter(),
|
|
526
|
+
},
|
|
527
|
+
}}
|
|
528
|
+
>
|
|
529
|
+
<App />
|
|
530
|
+
</ShortVideoProvider>
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
---
|
|
534
|
+
|
|
535
|
+
## π LiΓͺn kαΊΏt vα»i cΓ‘c Packages
|
|
536
|
+
|
|
537
|
+
| Package | Quan hα» vα»i SDK |
|
|
538
|
+
|---------|-----------------|
|
|
539
|
+
| `@xhub-short/contracts` | SDK re-export types/interfaces |
|
|
540
|
+
| `@xhub-short/core` | SDK wraps core managers vα»i React hooks |
|
|
541
|
+
| `@xhub-short/adapters` | SDK inject adapters vΓ o core managers |
|
|
542
|
+
| `@xhub-short/ui` | UI components sα» dα»₯ng SDK hooks (Phase 4) |
|
|
543
|
+
| `@xhub-short/bridge` | Optional Flutter integration |
|
|
544
|
+
|
|
545
|
+
### Dependency Flow
|
|
546
|
+
|
|
547
|
+
```
|
|
548
|
+
contracts βββββββββββββββββββββββββββββββββββββββββββ
|
|
549
|
+
β² β
|
|
550
|
+
β β
|
|
551
|
+
core ββββββββββββββββββββββββββββ β
|
|
552
|
+
β² β β
|
|
553
|
+
β β β
|
|
554
|
+
adapters ββββββββββββ β β
|
|
555
|
+
β² β β β
|
|
556
|
+
β β β β
|
|
557
|
+
βββββββββββββββββ΄βββββββββββ΄ββββββββββ sdk ββββ
|
|
558
|
+
β
|
|
559
|
+
βΌ
|
|
560
|
+
Host App
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## β οΈ LΖ°u Γ½ quan trα»ng
|
|
566
|
+
|
|
567
|
+
### SSR Safety
|
|
568
|
+
- TαΊ₯t cαΊ£ hooks sα» dα»₯ng `useSyncExternalStore`
|
|
569
|
+
- Provider render fallback trΓͺn server
|
|
570
|
+
- SDK instance chα» tαΊ‘o trΓͺn client
|
|
571
|
+
|
|
572
|
+
### Memory Management
|
|
573
|
+
- `sdk.destroy()` Δược gα»i tα»± Δα»ng khi Provider unmount
|
|
574
|
+
- Max 3 video DOM nodes (via ResourceGovernor)
|
|
575
|
+
- LRU cache eviction trong FeedManager
|
|
576
|
+
|
|
577
|
+
### Deprecated APIs
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
// β DEPRECATED - Singleton gΓ’y issues vα»i SSR/testing
|
|
581
|
+
const sdk = getSDK(config);
|
|
582
|
+
|
|
583
|
+
// β
RECOMMENDED - Sα» dα»₯ng Provider
|
|
584
|
+
<ShortVideoProvider config={config}>
|
|
585
|
+
<App />
|
|
586
|
+
</ShortVideoProvider>
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
## π TΓ i liα»u liΓͺn quan
|
|
592
|
+
|
|
593
|
+
- [ADD.md](/docs/ADD.md) - System Architecture
|
|
594
|
+
- [TECH_STACK.md](/docs/TECH_STACK.md) - Technology Stack
|
|
595
|
+
- [packages/core/README.md](/packages/core/README.md) - Core Domain
|
|
596
|
+
- [packages/adapters/README.md](/packages/adapters/README.md) - Adapters
|