react-native-tpstreams 0.2.14 → 0.2.16
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 +322 -4
- package/android/build.gradle +1 -1
- package/android/gradle.properties +1 -0
- package/android/src/main/java/com/tpstreams/TPStreamsDownloadModule.kt +79 -1
- package/android/src/main/java/com/tpstreams/TPStreamsRNPlayerView.kt +28 -1
- package/android/src/main/java/com/tpstreams/TPStreamsRNPlayerViewManager.kt +24 -0
- package/lib/module/TPStreamsDownload.js +11 -1
- package/lib/module/TPStreamsDownload.js.map +1 -1
- package/lib/module/TPStreamsPlayer.js +19 -1
- package/lib/module/TPStreamsPlayer.js.map +1 -1
- package/lib/module/TPStreamsPlayerViewNativeComponent.ts +7 -0
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/TPStreamsDownload.d.ts +7 -0
- package/lib/typescript/src/TPStreamsDownload.d.ts.map +1 -1
- package/lib/typescript/src/TPStreamsPlayer.d.ts +4 -0
- package/lib/typescript/src/TPStreamsPlayer.d.ts.map +1 -1
- package/lib/typescript/src/TPStreamsPlayerViewNativeComponent.d.ts +5 -0
- package/lib/typescript/src/TPStreamsPlayerViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/TPStreamsDownload.tsx +27 -1
- package/src/TPStreamsPlayer.tsx +27 -0
- package/src/TPStreamsPlayerViewNativeComponent.ts +7 -0
- package/src/index.tsx +5 -0
package/README.md
CHANGED
|
@@ -75,6 +75,8 @@ import { TPStreamsPlayerView } from "react-native-tpstreams";
|
|
|
75
75
|
|
|
76
76
|
- `onError(error: {message: string, code: number, details?: string})`: Fires when an error occurs.
|
|
77
77
|
|
|
78
|
+
- `onAccessTokenExpired(videoId: string, callback: (newToken: string) => void)`: Fires when the access token expires. Call the callback with a new token to continue playback.
|
|
79
|
+
|
|
78
80
|
---
|
|
79
81
|
|
|
80
82
|
## Player Props
|
|
@@ -91,6 +93,8 @@ import { TPStreamsPlayerView } from "react-native-tpstreams";
|
|
|
91
93
|
|
|
92
94
|
- `enableDownload`: (Optional) Whether to enable download functionality for the video. When set to true, the player will show a download button. Default is false.
|
|
93
95
|
|
|
96
|
+
- `downloadMetadata`: (Optional) Custom metadata to attach to downloads. Accepts an object with string key-value pairs. This metadata is stored with the download and can be retrieved later. Default is undefined.
|
|
97
|
+
|
|
94
98
|
---
|
|
95
99
|
|
|
96
100
|
## Downloads
|
|
@@ -113,15 +117,40 @@ import { TPStreamsPlayerView } from "react-native-tpstreams";
|
|
|
113
117
|
|
|
114
118
|
- `getAllDownloads()`: Gets all downloaded videos. Returns `Promise<DownloadItem[]>`.
|
|
115
119
|
|
|
120
|
+
### Real-time Download Progress
|
|
121
|
+
|
|
122
|
+
The library provides real-time download progress updates for optimal performance:
|
|
123
|
+
|
|
124
|
+
#### Progress Listener Methods
|
|
125
|
+
|
|
126
|
+
- `addDownloadProgressListener()`: Starts listening for download progress updates. Returns `Promise<void>`.
|
|
127
|
+
|
|
128
|
+
- `removeDownloadProgressListener()`: Stops listening for download progress updates. Returns `Promise<void>`.
|
|
129
|
+
|
|
130
|
+
- `onDownloadProgressChanged(listener: DownloadProgressListener)`: Adds a listener for progress changes. Returns `EmitterSubscription`.
|
|
131
|
+
|
|
132
|
+
#### Progress Listener Types
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// Progress update event (uses existing DownloadItem interface)
|
|
136
|
+
type DownloadProgressChange = DownloadItem;
|
|
137
|
+
|
|
138
|
+
// Listener function type
|
|
139
|
+
type DownloadProgressListener = (downloads: DownloadProgressChange[]) => void;
|
|
140
|
+
```
|
|
141
|
+
|
|
116
142
|
### Download Item
|
|
117
143
|
|
|
118
144
|
The download item object (`DownloadItem`) contains information about a downloaded or downloading video, including:
|
|
119
145
|
|
|
120
|
-
- `
|
|
121
|
-
- `
|
|
122
|
-
- `progressPercentage`: Download progress from 0 to 100.
|
|
123
|
-
- `title`: The title of the video Asset.
|
|
146
|
+
- `videoId`: The ID of the video.
|
|
147
|
+
- `title`: The title of the video.
|
|
124
148
|
- `thumbnailUrl`: URL to the video thumbnail (if available).
|
|
149
|
+
- `totalBytes`: Total size of the video in bytes.
|
|
150
|
+
- `downloadedBytes`: Number of bytes downloaded so far.
|
|
151
|
+
- `progressPercentage`: Download progress from 0 to 100.
|
|
152
|
+
- `state`: The current state of the download as String (Queued, Downloading, Completed, Failed, Removing, Restarting, Paused).
|
|
153
|
+
- `metadata`: Custom metadata attached to the download as a JSON string (if provided during download).
|
|
125
154
|
|
|
126
155
|
---
|
|
127
156
|
|
|
@@ -173,6 +202,16 @@ function TPStreamsPlayerExample() {
|
|
|
173
202
|
onPlaybackSpeedChanged={(speed) => console.log(`Speed changed: ${speed}x`)}
|
|
174
203
|
onIsLoadingChanged={(isLoading) => console.log(`Loading: ${isLoading}`)}
|
|
175
204
|
onError={(error) => console.error('Player error:', error)}
|
|
205
|
+
onAccessTokenExpired={async (videoId, callback) => {
|
|
206
|
+
// Fetch a new token from your server
|
|
207
|
+
const newToken = await getNewTokenForVideo(videoId);
|
|
208
|
+
callback(newToken);
|
|
209
|
+
}}
|
|
210
|
+
downloadMetadata={{
|
|
211
|
+
category: 'educational',
|
|
212
|
+
subject: 'mathematics',
|
|
213
|
+
level: 'intermediate'
|
|
214
|
+
}}
|
|
176
215
|
/>
|
|
177
216
|
|
|
178
217
|
<Button title="Play" onPress={handlePlay} />
|
|
@@ -284,6 +323,285 @@ const removeVideoDownload = async (videoId: string) => {
|
|
|
284
323
|
};
|
|
285
324
|
```
|
|
286
325
|
|
|
326
|
+
## Real-time Download Progress Example
|
|
327
|
+
|
|
328
|
+
Here's a complete example showing how to implement real-time download progress in a React Native component:
|
|
329
|
+
|
|
330
|
+
```jsx
|
|
331
|
+
import React, { useState, useEffect } from 'react';
|
|
332
|
+
import {
|
|
333
|
+
View,
|
|
334
|
+
Text,
|
|
335
|
+
StyleSheet,
|
|
336
|
+
TouchableOpacity,
|
|
337
|
+
ScrollView,
|
|
338
|
+
Alert,
|
|
339
|
+
} from 'react-native';
|
|
340
|
+
import {
|
|
341
|
+
addDownloadProgressListener,
|
|
342
|
+
removeDownloadProgressListener,
|
|
343
|
+
onDownloadProgressChanged,
|
|
344
|
+
pauseDownload,
|
|
345
|
+
resumeDownload,
|
|
346
|
+
removeDownload,
|
|
347
|
+
type DownloadItem,
|
|
348
|
+
type DownloadProgressChange,
|
|
349
|
+
} from 'react-native-tpstreams';
|
|
350
|
+
|
|
351
|
+
const DownloadProgressExample = () => {
|
|
352
|
+
const [downloads, setDownloads] = useState<DownloadItem[]>([]);
|
|
353
|
+
const [isInitializing, setIsInitializing] = useState(true);
|
|
354
|
+
|
|
355
|
+
useEffect(() => {
|
|
356
|
+
// Setup progress listener when component mounts
|
|
357
|
+
const setupProgressListener = async () => {
|
|
358
|
+
try {
|
|
359
|
+
// Start listening for progress updates
|
|
360
|
+
await addDownloadProgressListener();
|
|
361
|
+
|
|
362
|
+
// Add listener for progress updates
|
|
363
|
+
const subscription = onDownloadProgressChanged((downloads: DownloadProgressChange[]) => {
|
|
364
|
+
console.log('Progress changes received:', downloads.length, 'downloads');
|
|
365
|
+
|
|
366
|
+
// Simply replace the state with the complete list from native
|
|
367
|
+
setDownloads(downloads);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// Cleanup function
|
|
371
|
+
return () => {
|
|
372
|
+
subscription.remove(); // Remove the listener
|
|
373
|
+
removeDownloadProgressListener(); // Stop listening
|
|
374
|
+
};
|
|
375
|
+
} catch (error) {
|
|
376
|
+
console.error('Failed to setup progress listener:', error);
|
|
377
|
+
setIsInitializing(false);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
setupProgressListener();
|
|
382
|
+
}, []);
|
|
383
|
+
|
|
384
|
+
const handlePauseDownload = async (videoId: string) => {
|
|
385
|
+
try {
|
|
386
|
+
await pauseDownload(videoId);
|
|
387
|
+
console.log('Download paused successfully');
|
|
388
|
+
} catch (error) {
|
|
389
|
+
console.error('Error pausing download:', error);
|
|
390
|
+
Alert.alert('Error', 'Failed to pause download');
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
const handleResumeDownload = async (videoId: string) => {
|
|
395
|
+
try {
|
|
396
|
+
await resumeDownload(videoId);
|
|
397
|
+
console.log('Download resumed successfully');
|
|
398
|
+
} catch (error) {
|
|
399
|
+
console.error('Error resuming download:', error);
|
|
400
|
+
Alert.alert('Error', 'Failed to resume download');
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
const handleRemoveDownload = async (videoId: string) => {
|
|
405
|
+
try {
|
|
406
|
+
await removeDownload(videoId);
|
|
407
|
+
console.log('Download removed successfully');
|
|
408
|
+
} catch (error) {
|
|
409
|
+
console.error('Error removing download:', error);
|
|
410
|
+
Alert.alert('Error', 'Failed to remove download');
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
const renderDownloadItem = (item: DownloadItem) => {
|
|
415
|
+
const isCompleted = item.state === 'Completed';
|
|
416
|
+
const isDownloading = item.state === 'Downloading';
|
|
417
|
+
const isPaused = item.state === 'Paused';
|
|
418
|
+
|
|
419
|
+
return (
|
|
420
|
+
<View key={item.videoId} style={styles.downloadItem}>
|
|
421
|
+
<Text style={styles.title}>{item.title}</Text>
|
|
422
|
+
<Text style={styles.status}>Status: {item.state}</Text>
|
|
423
|
+
|
|
424
|
+
{!isCompleted && (
|
|
425
|
+
<View style={styles.progressContainer}>
|
|
426
|
+
<View style={styles.progressBar}>
|
|
427
|
+
<View
|
|
428
|
+
style={[
|
|
429
|
+
styles.progressFill,
|
|
430
|
+
{ width: `${item.progressPercentage}%` }
|
|
431
|
+
]}
|
|
432
|
+
/>
|
|
433
|
+
</View>
|
|
434
|
+
<Text style={styles.progressText}>
|
|
435
|
+
{item.progressPercentage.toFixed(1)}%
|
|
436
|
+
</Text>
|
|
437
|
+
</View>
|
|
438
|
+
)}
|
|
439
|
+
|
|
440
|
+
{item.totalBytes > 0 && (
|
|
441
|
+
<Text style={styles.bytesText}>
|
|
442
|
+
{(item.downloadedBytes / (1024 * 1024)).toFixed(1)} MB /
|
|
443
|
+
{(item.totalBytes / (1024 * 1024)).toFixed(1)} MB
|
|
444
|
+
</Text>
|
|
445
|
+
)}
|
|
446
|
+
|
|
447
|
+
<View style={styles.buttonContainer}>
|
|
448
|
+
{!isCompleted && (
|
|
449
|
+
<>
|
|
450
|
+
{isDownloading && (
|
|
451
|
+
<TouchableOpacity
|
|
452
|
+
style={styles.button}
|
|
453
|
+
onPress={() => handlePauseDownload(item.videoId)}
|
|
454
|
+
>
|
|
455
|
+
<Text style={styles.buttonText}>Pause</Text>
|
|
456
|
+
</TouchableOpacity>
|
|
457
|
+
)}
|
|
458
|
+
|
|
459
|
+
{isPaused && (
|
|
460
|
+
<TouchableOpacity
|
|
461
|
+
style={styles.button}
|
|
462
|
+
onPress={() => handleResumeDownload(item.videoId)}
|
|
463
|
+
>
|
|
464
|
+
<Text style={styles.buttonText}>Resume</Text>
|
|
465
|
+
</TouchableOpacity>
|
|
466
|
+
)}
|
|
467
|
+
</>
|
|
468
|
+
)}
|
|
469
|
+
|
|
470
|
+
<TouchableOpacity
|
|
471
|
+
style={[styles.button, styles.removeButton]}
|
|
472
|
+
onPress={() => handleRemoveDownload(item.videoId)}
|
|
473
|
+
>
|
|
474
|
+
<Text style={styles.buttonText}>Remove</Text>
|
|
475
|
+
</TouchableOpacity>
|
|
476
|
+
</View>
|
|
477
|
+
</View>
|
|
478
|
+
);
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
if (isInitializing) {
|
|
482
|
+
return (
|
|
483
|
+
<View style={styles.container}>
|
|
484
|
+
<Text>Loading downloads...</Text>
|
|
485
|
+
</View>
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
return (
|
|
490
|
+
<ScrollView style={styles.container}>
|
|
491
|
+
<Text style={styles.header}>Downloads ({downloads.length})</Text>
|
|
492
|
+
|
|
493
|
+
{downloads.length > 0 ? (
|
|
494
|
+
downloads.map(renderDownloadItem)
|
|
495
|
+
) : (
|
|
496
|
+
<Text style={styles.emptyText}>No downloads available</Text>
|
|
497
|
+
)}
|
|
498
|
+
</ScrollView>
|
|
499
|
+
);
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
const styles = StyleSheet.create({
|
|
503
|
+
container: {
|
|
504
|
+
flex: 1,
|
|
505
|
+
padding: 16,
|
|
506
|
+
backgroundColor: '#f5f5f5',
|
|
507
|
+
},
|
|
508
|
+
header: {
|
|
509
|
+
fontSize: 20,
|
|
510
|
+
fontWeight: 'bold',
|
|
511
|
+
marginBottom: 16,
|
|
512
|
+
},
|
|
513
|
+
downloadItem: {
|
|
514
|
+
backgroundColor: '#fff',
|
|
515
|
+
padding: 16,
|
|
516
|
+
marginBottom: 12,
|
|
517
|
+
borderRadius: 8,
|
|
518
|
+
shadowColor: '#000',
|
|
519
|
+
shadowOffset: { width: 0, height: 2 },
|
|
520
|
+
shadowOpacity: 0.1,
|
|
521
|
+
shadowRadius: 4,
|
|
522
|
+
elevation: 3,
|
|
523
|
+
},
|
|
524
|
+
title: {
|
|
525
|
+
fontSize: 16,
|
|
526
|
+
fontWeight: 'bold',
|
|
527
|
+
marginBottom: 8,
|
|
528
|
+
},
|
|
529
|
+
status: {
|
|
530
|
+
fontSize: 14,
|
|
531
|
+
color: '#666',
|
|
532
|
+
marginBottom: 8,
|
|
533
|
+
},
|
|
534
|
+
progressContainer: {
|
|
535
|
+
flexDirection: 'row',
|
|
536
|
+
alignItems: 'center',
|
|
537
|
+
marginBottom: 8,
|
|
538
|
+
},
|
|
539
|
+
progressBar: {
|
|
540
|
+
flex: 1,
|
|
541
|
+
height: 8,
|
|
542
|
+
backgroundColor: '#eee',
|
|
543
|
+
borderRadius: 4,
|
|
544
|
+
marginRight: 12,
|
|
545
|
+
},
|
|
546
|
+
progressFill: {
|
|
547
|
+
height: '100%',
|
|
548
|
+
backgroundColor: '#007AFF',
|
|
549
|
+
borderRadius: 4,
|
|
550
|
+
},
|
|
551
|
+
progressText: {
|
|
552
|
+
fontSize: 12,
|
|
553
|
+
color: '#666',
|
|
554
|
+
width: 40,
|
|
555
|
+
},
|
|
556
|
+
bytesText: {
|
|
557
|
+
fontSize: 12,
|
|
558
|
+
color: '#666',
|
|
559
|
+
marginBottom: 12,
|
|
560
|
+
},
|
|
561
|
+
buttonContainer: {
|
|
562
|
+
flexDirection: 'row',
|
|
563
|
+
gap: 8,
|
|
564
|
+
},
|
|
565
|
+
button: {
|
|
566
|
+
paddingVertical: 8,
|
|
567
|
+
paddingHorizontal: 16,
|
|
568
|
+
backgroundColor: '#007AFF',
|
|
569
|
+
borderRadius: 6,
|
|
570
|
+
},
|
|
571
|
+
removeButton: {
|
|
572
|
+
backgroundColor: '#FF3B30',
|
|
573
|
+
},
|
|
574
|
+
buttonText: {
|
|
575
|
+
color: '#fff',
|
|
576
|
+
fontSize: 14,
|
|
577
|
+
fontWeight: '600',
|
|
578
|
+
},
|
|
579
|
+
emptyText: {
|
|
580
|
+
textAlign: 'center',
|
|
581
|
+
color: '#666',
|
|
582
|
+
fontSize: 16,
|
|
583
|
+
},
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
export default DownloadProgressExample;
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
### Key Features of the Real-time Progress System:
|
|
590
|
+
|
|
591
|
+
1. **Real-time Updates**: Progress bars and status update in real-time
|
|
592
|
+
2. **Automatic UI Updates**: UI automatically reflects current download states
|
|
593
|
+
3. **Efficient State Management**: Uses functional state updates to avoid race conditions
|
|
594
|
+
4. **Proper Cleanup**: Removes listeners when component unmounts
|
|
595
|
+
5. **Error Handling**: Graceful error handling with user feedback
|
|
596
|
+
6. **Type Safety**: Full TypeScript support with proper types
|
|
597
|
+
|
|
598
|
+
### Best Practices:
|
|
599
|
+
|
|
600
|
+
1. **Start listening when needed**: Only start the progress listener when your screen is active
|
|
601
|
+
2. **Stop listening when not needed**: Always stop listening to save resources
|
|
602
|
+
3. **Use functional state updates**: Prevents race conditions with concurrent updates
|
|
603
|
+
4. **Debounce if needed**: Consider debouncing updates for better UI performance
|
|
604
|
+
|
|
287
605
|
---
|
|
288
606
|
|
|
289
607
|
## Contributing
|
package/android/build.gradle
CHANGED
|
@@ -82,7 +82,7 @@ def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
|
82
82
|
dependencies {
|
|
83
83
|
implementation "com.facebook.react:react-android"
|
|
84
84
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
85
|
-
implementation
|
|
85
|
+
implementation "com.github.testpress:TPStreamsAndroidPlayer:${getExtOrDefault('tpstreamsAndroidPlayerVersion')}"
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
react {
|
|
@@ -6,19 +6,89 @@ import com.facebook.react.bridge.Arguments
|
|
|
6
6
|
import com.facebook.react.bridge.ReactMethod
|
|
7
7
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
8
8
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
9
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
9
10
|
import com.tpstreams.player.download.DownloadClient
|
|
10
11
|
import com.tpstreams.player.download.DownloadItem
|
|
11
12
|
|
|
12
|
-
class TPStreamsDownloadModule(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
|
|
13
|
+
class TPStreamsDownloadModule(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext), DownloadClient.Listener {
|
|
13
14
|
|
|
14
15
|
private val downloadClient: DownloadClient by lazy {
|
|
15
16
|
DownloadClient.getInstance(reactContext)
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
private var isListening = false
|
|
20
|
+
|
|
18
21
|
override fun getName(): String {
|
|
19
22
|
return "TPStreamsDownload"
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
@ReactMethod
|
|
26
|
+
fun addDownloadProgressListener(promise: Promise) {
|
|
27
|
+
try {
|
|
28
|
+
if (!isListening) {
|
|
29
|
+
downloadClient.addListener(this)
|
|
30
|
+
isListening = true
|
|
31
|
+
Log.d(TAG, "Started listening for download progress")
|
|
32
|
+
}
|
|
33
|
+
promise.resolve(null)
|
|
34
|
+
} catch (e: Exception) {
|
|
35
|
+
Log.e(TAG, "Error starting progress listener: ${e.message}", e)
|
|
36
|
+
promise.reject("PROGRESS_LISTENER_START_ERROR", e.message, e)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@ReactMethod
|
|
41
|
+
fun removeDownloadProgressListener(promise: Promise) {
|
|
42
|
+
try {
|
|
43
|
+
if (isListening) {
|
|
44
|
+
downloadClient.removeListener(this)
|
|
45
|
+
isListening = false
|
|
46
|
+
Log.d(TAG, "Stopped listening for download progress")
|
|
47
|
+
}
|
|
48
|
+
promise.resolve(null)
|
|
49
|
+
} catch (e: Exception) {
|
|
50
|
+
Log.e(TAG, "Error stopping progress listener: ${e.message}", e)
|
|
51
|
+
promise.reject("PROGRESS_LISTENER_STOP_ERROR", e.message, e)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
override fun onDownloadsChanged() {
|
|
56
|
+
try {
|
|
57
|
+
val currentDownloads = downloadClient.getAllDownloadItems()
|
|
58
|
+
|
|
59
|
+
val result = Arguments.createArray()
|
|
60
|
+
for (item in currentDownloads) {
|
|
61
|
+
val map = Arguments.createMap()
|
|
62
|
+
map.putString("videoId", item.assetId)
|
|
63
|
+
map.putString("title", item.title)
|
|
64
|
+
item.thumbnailUrl?.let { map.putString("thumbnailUrl", it) }
|
|
65
|
+
map.putDouble("totalBytes", item.totalBytes.toDouble())
|
|
66
|
+
map.putDouble("downloadedBytes", item.downloadedBytes.toDouble())
|
|
67
|
+
map.putDouble("progressPercentage", item.progressPercentage.toDouble())
|
|
68
|
+
map.putString("state", downloadClient.getDownloadStatus(item.assetId))
|
|
69
|
+
|
|
70
|
+
val metadataJson = org.json.JSONObject()
|
|
71
|
+
item.metadata.forEach { (key, value) ->
|
|
72
|
+
metadataJson.put(key, value)
|
|
73
|
+
}
|
|
74
|
+
map.putString("metadata", metadataJson.toString())
|
|
75
|
+
|
|
76
|
+
result.pushMap(map)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
emitEvent("onDownloadProgressChanged", result)
|
|
80
|
+
|
|
81
|
+
} catch (e: Exception) {
|
|
82
|
+
Log.e(TAG, "Error in onDownloadsChanged: ${e.message}", e)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private fun emitEvent(eventName: String, data: Any) {
|
|
87
|
+
reactContext
|
|
88
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
89
|
+
.emit(eventName, data)
|
|
90
|
+
}
|
|
91
|
+
|
|
22
92
|
@ReactMethod
|
|
23
93
|
fun pauseDownload(videoId: String, promise: Promise) {
|
|
24
94
|
try {
|
|
@@ -112,6 +182,14 @@ class TPStreamsDownloadModule(private val reactContext: ReactApplicationContext)
|
|
|
112
182
|
map.putDouble("progressPercentage", item.progressPercentage.toDouble())
|
|
113
183
|
map.putString("state", downloadClient.getDownloadStatus(item.assetId))
|
|
114
184
|
|
|
185
|
+
try {
|
|
186
|
+
val metadataJson = org.json.JSONObject(item.metadata as Map<*, *>)
|
|
187
|
+
map.putString("metadata", metadataJson.toString())
|
|
188
|
+
} catch (e: Exception) {
|
|
189
|
+
Log.w(TAG, "Error serializing metadata for item ${item.assetId}: ${e.message}")
|
|
190
|
+
map.putString("metadata", "{}")
|
|
191
|
+
}
|
|
192
|
+
|
|
115
193
|
result.pushMap(map)
|
|
116
194
|
}
|
|
117
195
|
|
|
@@ -23,6 +23,8 @@ class TPStreamsRNPlayerView(context: ThemedReactContext) : FrameLayout(context)
|
|
|
23
23
|
private var startAt: Long = 0
|
|
24
24
|
private var showDefaultCaptions: Boolean = false
|
|
25
25
|
private var enableDownload: Boolean = false
|
|
26
|
+
private var downloadMetadata: Map<String, String>? = null
|
|
27
|
+
private var accessTokenCallback: ((String) -> Unit)? = null
|
|
26
28
|
|
|
27
29
|
init {
|
|
28
30
|
addView(playerView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
|
|
@@ -76,6 +78,18 @@ class TPStreamsRNPlayerView(context: ThemedReactContext) : FrameLayout(context)
|
|
|
76
78
|
fun setEnableDownload(enableDownload: Boolean) {
|
|
77
79
|
this.enableDownload = enableDownload
|
|
78
80
|
}
|
|
81
|
+
|
|
82
|
+
fun setDownloadMetadata(metadata: Map<String, String>?) {
|
|
83
|
+
this.downloadMetadata = metadata
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fun setNewAccessToken(newToken: String) {
|
|
87
|
+
Log.d("TPStreamsRNPlayerView", "Setting new access token")
|
|
88
|
+
accessTokenCallback?.let { callback ->
|
|
89
|
+
callback(newToken)
|
|
90
|
+
accessTokenCallback = null
|
|
91
|
+
} ?: Log.w("TPStreamsRNPlayerView", "No callback available for token refresh")
|
|
92
|
+
}
|
|
79
93
|
|
|
80
94
|
fun tryCreatePlayer() {
|
|
81
95
|
if (videoId.isNullOrEmpty() || accessToken.isNullOrEmpty()) return
|
|
@@ -89,9 +103,21 @@ class TPStreamsRNPlayerView(context: ThemedReactContext) : FrameLayout(context)
|
|
|
89
103
|
shouldAutoPlay,
|
|
90
104
|
startAt,
|
|
91
105
|
enableDownload,
|
|
92
|
-
showDefaultCaptions
|
|
106
|
+
showDefaultCaptions,
|
|
107
|
+
downloadMetadata
|
|
93
108
|
)
|
|
94
109
|
|
|
110
|
+
player?.listener = object : TPStreamsPlayer.Listener {
|
|
111
|
+
override fun onAccessTokenExpired(videoId: String, callback: (String) -> Unit) {
|
|
112
|
+
if (accessTokenCallback != null) {
|
|
113
|
+
Log.w("TPStreamsRNPlayerView", "onAccessTokenExpired called while another refresh is in progress. Ignoring.")
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
accessTokenCallback = callback
|
|
117
|
+
emitEvent("onAccessTokenExpired", mapOf("videoId" to videoId))
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
95
121
|
// Add player event listeners
|
|
96
122
|
player?.addListener(createPlayerListener())
|
|
97
123
|
|
|
@@ -188,5 +214,6 @@ class TPStreamsRNPlayerView(context: ThemedReactContext) : FrameLayout(context)
|
|
|
188
214
|
Log.e("TPStreamsRN", "Error releasing player", e)
|
|
189
215
|
}
|
|
190
216
|
player = null
|
|
217
|
+
accessTokenCallback = null
|
|
191
218
|
}
|
|
192
219
|
}
|
|
@@ -26,6 +26,7 @@ class TPStreamsRNPlayerViewManager : SimpleViewManager<TPStreamsRNPlayerView>(),
|
|
|
26
26
|
private const val EVENT_PLAYBACK_SPEED_CHANGED = "onPlaybackSpeedChanged"
|
|
27
27
|
private const val EVENT_IS_LOADING_CHANGED = "onIsLoadingChanged"
|
|
28
28
|
private const val EVENT_ERROR = "onError"
|
|
29
|
+
private const val EVENT_ACCESS_TOKEN_EXPIRED = "onAccessTokenExpired"
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
private val mDelegate: ViewManagerDelegate<TPStreamsRNPlayerView> =
|
|
@@ -46,6 +47,7 @@ class TPStreamsRNPlayerViewManager : SimpleViewManager<TPStreamsRNPlayerView>(),
|
|
|
46
47
|
.put(EVENT_PLAYBACK_SPEED_CHANGED, MapBuilder.of("registrationName", EVENT_PLAYBACK_SPEED_CHANGED))
|
|
47
48
|
.put(EVENT_IS_LOADING_CHANGED, MapBuilder.of("registrationName", EVENT_IS_LOADING_CHANGED))
|
|
48
49
|
.put(EVENT_ERROR, MapBuilder.of("registrationName", EVENT_ERROR))
|
|
50
|
+
.put(EVENT_ACCESS_TOKEN_EXPIRED, MapBuilder.of("registrationName", EVENT_ACCESS_TOKEN_EXPIRED))
|
|
49
51
|
.build()
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -82,6 +84,24 @@ class TPStreamsRNPlayerViewManager : SimpleViewManager<TPStreamsRNPlayerView>(),
|
|
|
82
84
|
view.setEnableDownload(enableDownload)
|
|
83
85
|
}
|
|
84
86
|
|
|
87
|
+
@ReactProp(name = "downloadMetadata")
|
|
88
|
+
override fun setDownloadMetadata(view: TPStreamsRNPlayerView, metadata: String?) {
|
|
89
|
+
val metadataMap = if (!metadata.isNullOrEmpty()) {
|
|
90
|
+
try {
|
|
91
|
+
val jsonObject = org.json.JSONObject(metadata)
|
|
92
|
+
val map = jsonObject.keys()
|
|
93
|
+
.asSequence()
|
|
94
|
+
.associate { it to jsonObject.getString(it) }
|
|
95
|
+
.toMutableMap()
|
|
96
|
+
map
|
|
97
|
+
} catch (e: org.json.JSONException) {
|
|
98
|
+
android.util.Log.w("TPStreamsRN", "Error parsing download metadata: ${e.message}")
|
|
99
|
+
null
|
|
100
|
+
}
|
|
101
|
+
} else null
|
|
102
|
+
view.setDownloadMetadata(metadataMap)
|
|
103
|
+
}
|
|
104
|
+
|
|
85
105
|
// Command implementations
|
|
86
106
|
override fun play(view: TPStreamsRNPlayerView) {
|
|
87
107
|
view.play()
|
|
@@ -115,6 +135,10 @@ class TPStreamsRNPlayerViewManager : SimpleViewManager<TPStreamsRNPlayerView>(),
|
|
|
115
135
|
view.getPlaybackSpeed()
|
|
116
136
|
}
|
|
117
137
|
|
|
138
|
+
override fun setNewAccessToken(view: TPStreamsRNPlayerView, newToken: String) {
|
|
139
|
+
view.setNewAccessToken(newToken)
|
|
140
|
+
}
|
|
141
|
+
|
|
118
142
|
override fun onAfterUpdateTransaction(view: TPStreamsRNPlayerView) {
|
|
119
143
|
super.onAfterUpdateTransaction(view)
|
|
120
144
|
view.tryCreatePlayer()
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { NativeModules } from 'react-native';
|
|
3
|
+
import { NativeModules, NativeEventEmitter } from 'react-native';
|
|
4
4
|
const {
|
|
5
5
|
TPStreamsDownload
|
|
6
6
|
} = NativeModules;
|
|
7
|
+
const downloadEventEmitter = new NativeEventEmitter(TPStreamsDownload);
|
|
8
|
+
export function addDownloadProgressListener() {
|
|
9
|
+
return TPStreamsDownload.addDownloadProgressListener();
|
|
10
|
+
}
|
|
11
|
+
export function removeDownloadProgressListener() {
|
|
12
|
+
return TPStreamsDownload.removeDownloadProgressListener();
|
|
13
|
+
}
|
|
14
|
+
export function onDownloadProgressChanged(listener) {
|
|
15
|
+
return downloadEventEmitter.addListener('onDownloadProgressChanged', listener);
|
|
16
|
+
}
|
|
7
17
|
export function pauseDownload(videoId) {
|
|
8
18
|
return TPStreamsDownload.pauseDownload(videoId);
|
|
9
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","TPStreamsDownload","pauseDownload","videoId","resumeDownload","removeDownload","isDownloaded","isDownloading","isPaused","getDownloadStatus","getAllDownloads"],"sourceRoot":"../../src","sources":["TPStreamsDownload.tsx"],"mappings":";;AAAA,SAASA,aAAa,QAAQ,cAAc;
|
|
1
|
+
{"version":3,"names":["NativeModules","NativeEventEmitter","TPStreamsDownload","downloadEventEmitter","addDownloadProgressListener","removeDownloadProgressListener","onDownloadProgressChanged","listener","addListener","pauseDownload","videoId","resumeDownload","removeDownload","isDownloaded","isDownloading","isPaused","getDownloadStatus","getAllDownloads"],"sourceRoot":"../../src","sources":["TPStreamsDownload.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,kBAAkB,QAAQ,cAAc;AAGhE,MAAM;EAAEC;AAAkB,CAAC,GAAGF,aAAa;AAkB3C,MAAMG,oBAAoB,GAAG,IAAIF,kBAAkB,CAACC,iBAAiB,CAAC;AAEtE,OAAO,SAASE,2BAA2BA,CAAA,EAAkB;EAC3D,OAAOF,iBAAiB,CAACE,2BAA2B,CAAC,CAAC;AACxD;AAEA,OAAO,SAASC,8BAA8BA,CAAA,EAAkB;EAC9D,OAAOH,iBAAiB,CAACG,8BAA8B,CAAC,CAAC;AAC3D;AAEA,OAAO,SAASC,yBAAyBA,CACvCC,QAAkC,EACb;EACrB,OAAOJ,oBAAoB,CAACK,WAAW,CACrC,2BAA2B,EAC3BD,QACF,CAAC;AACH;AAEA,OAAO,SAASE,aAAaA,CAACC,OAAe,EAAiB;EAC5D,OAAOR,iBAAiB,CAACO,aAAa,CAACC,OAAO,CAAC;AACjD;AAEA,OAAO,SAASC,cAAcA,CAACD,OAAe,EAAiB;EAC7D,OAAOR,iBAAiB,CAACS,cAAc,CAACD,OAAO,CAAC;AAClD;AAEA,OAAO,SAASE,cAAcA,CAACF,OAAe,EAAiB;EAC7D,OAAOR,iBAAiB,CAACU,cAAc,CAACF,OAAO,CAAC;AAClD;AAEA,OAAO,SAASG,YAAYA,CAACH,OAAe,EAAoB;EAC9D,OAAOR,iBAAiB,CAACW,YAAY,CAACH,OAAO,CAAC;AAChD;AAEA,OAAO,SAASI,aAAaA,CAACJ,OAAe,EAAoB;EAC/D,OAAOR,iBAAiB,CAACY,aAAa,CAACJ,OAAO,CAAC;AACjD;AAEA,OAAO,SAASK,QAAQA,CAACL,OAAe,EAAoB;EAC1D,OAAOR,iBAAiB,CAACa,QAAQ,CAACL,OAAO,CAAC;AAC5C;AAEA,OAAO,SAASM,iBAAiBA,CAACN,OAAe,EAAmB;EAClE,OAAOR,iBAAiB,CAACc,iBAAiB,CAACN,OAAO,CAAC;AACrD;AAEA,OAAO,SAASO,eAAeA,CAAA,EAA4B;EACzD,OAAOf,iBAAiB,CAACe,eAAe,CAAC,CAAC;AAC5C","ignoreList":[]}
|
|
@@ -24,12 +24,14 @@ const TPStreamsPlayerView = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
24
24
|
startAt,
|
|
25
25
|
enableDownload,
|
|
26
26
|
showDefaultCaptions,
|
|
27
|
+
downloadMetadata,
|
|
27
28
|
style,
|
|
28
29
|
onPlayerStateChanged,
|
|
29
30
|
onIsPlayingChanged,
|
|
30
31
|
onPlaybackSpeedChanged,
|
|
31
32
|
onIsLoadingChanged,
|
|
32
33
|
onError,
|
|
34
|
+
onAccessTokenExpired,
|
|
33
35
|
...restProps
|
|
34
36
|
} = props;
|
|
35
37
|
const nativeRef = useRef(null);
|
|
@@ -103,6 +105,20 @@ const TPStreamsPlayerView = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
103
105
|
details
|
|
104
106
|
});
|
|
105
107
|
}, [onError]);
|
|
108
|
+
const handleAccessTokenExpired = useCallback(event => {
|
|
109
|
+
if (onAccessTokenExpired) {
|
|
110
|
+
const {
|
|
111
|
+
videoId: expiredVideoId
|
|
112
|
+
} = event.nativeEvent;
|
|
113
|
+
onAccessTokenExpired(expiredVideoId, newToken => {
|
|
114
|
+
if (nativeRef.current) {
|
|
115
|
+
Commands.setNewAccessToken(nativeRef.current, newToken);
|
|
116
|
+
} else {
|
|
117
|
+
console.error('[RN] Native ref is not available');
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}, [onAccessTokenExpired]);
|
|
106
122
|
|
|
107
123
|
// Helper to create promise-based API methods
|
|
108
124
|
const createPromiseMethod = useCallback((command, eventKey) => {
|
|
@@ -147,6 +163,7 @@ const TPStreamsPlayerView = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
147
163
|
startAt,
|
|
148
164
|
enableDownload,
|
|
149
165
|
showDefaultCaptions,
|
|
166
|
+
downloadMetadata: downloadMetadata ? JSON.stringify(downloadMetadata) : undefined,
|
|
150
167
|
style,
|
|
151
168
|
onCurrentPosition,
|
|
152
169
|
onDuration,
|
|
@@ -156,7 +173,8 @@ const TPStreamsPlayerView = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
156
173
|
onIsPlayingChanged: handleIsPlayingChanged,
|
|
157
174
|
onPlaybackSpeedChanged: handlePlaybackSpeedChanged,
|
|
158
175
|
onIsLoadingChanged: handleIsLoadingChanged,
|
|
159
|
-
onError: handleError
|
|
176
|
+
onError: handleError,
|
|
177
|
+
onAccessTokenExpired: handleAccessTokenExpired
|
|
160
178
|
};
|
|
161
179
|
return /*#__PURE__*/_jsx(TPStreamsPlayerNative, {
|
|
162
180
|
...nativeProps,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["forwardRef","useImperativeHandle","useRef","useCallback","TPStreamsPlayerNative","Commands","jsx","_jsx","nextInstanceId","TPStreamsPlayerView","props","ref","videoId","accessToken","shouldAutoPlay","startAt","enableDownload","showDefaultCaptions","style","onPlayerStateChanged","onIsPlayingChanged","onPlaybackSpeedChanged","onIsLoadingChanged","onError","restProps","nativeRef","instanceId","promiseMap","onCurrentPosition","event","key","current","handler","resolve","nativeEvent","position","onDuration","duration","onIsPlaying","isPlaying","onPlaybackSpeed","speed","handlePlayerStateChanged","playbackState","handleIsPlayingChanged","handlePlaybackSpeedChanged","handleIsLoadingChanged","isLoading","handleError","message","code","details","Object","entries","forEach","reject","Error","createPromiseMethod","command","eventKey","Promise","setTimeout","play","pause","seekTo","positionMs","setPlaybackSpeed","getCurrentPosition","getDuration","getPlaybackSpeed","nativeProps"],"sourceRoot":"../../src","sources":["TPStreamsPlayer.tsx"],"mappings":";;AAAA,SAASA,UAAU,EAAEC,mBAAmB,EAAEC,MAAM,EAAEC,WAAW,QAAQ,OAAO;AAC5E,OAAOC,qBAAqB,IAC1BC,QAAQ,QACH,sCAAsC;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAO9C;AACA,IAAIC,cAAc,GAAG,CAAC;;AAEtB;;AAQA;;AAYA;;
|
|
1
|
+
{"version":3,"names":["forwardRef","useImperativeHandle","useRef","useCallback","TPStreamsPlayerNative","Commands","jsx","_jsx","nextInstanceId","TPStreamsPlayerView","props","ref","videoId","accessToken","shouldAutoPlay","startAt","enableDownload","showDefaultCaptions","downloadMetadata","style","onPlayerStateChanged","onIsPlayingChanged","onPlaybackSpeedChanged","onIsLoadingChanged","onError","onAccessTokenExpired","restProps","nativeRef","instanceId","promiseMap","onCurrentPosition","event","key","current","handler","resolve","nativeEvent","position","onDuration","duration","onIsPlaying","isPlaying","onPlaybackSpeed","speed","handlePlayerStateChanged","playbackState","handleIsPlayingChanged","handlePlaybackSpeedChanged","handleIsLoadingChanged","isLoading","handleError","message","code","details","Object","entries","forEach","reject","Error","handleAccessTokenExpired","expiredVideoId","newToken","setNewAccessToken","console","error","createPromiseMethod","command","eventKey","Promise","setTimeout","play","pause","seekTo","positionMs","setPlaybackSpeed","getCurrentPosition","getDuration","getPlaybackSpeed","nativeProps","JSON","stringify","undefined"],"sourceRoot":"../../src","sources":["TPStreamsPlayer.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -22,6 +22,7 @@ export interface NativeProps extends ViewProps {
|
|
|
22
22
|
startAt?: Double;
|
|
23
23
|
enableDownload?: boolean;
|
|
24
24
|
showDefaultCaptions?: boolean;
|
|
25
|
+
downloadMetadata?: string;
|
|
25
26
|
|
|
26
27
|
// Event props for receiving data from native methods
|
|
27
28
|
onCurrentPosition?: DirectEventHandler<{ position: Double }>;
|
|
@@ -35,6 +36,7 @@ export interface NativeProps extends ViewProps {
|
|
|
35
36
|
onPlaybackSpeedChanged?: DirectEventHandler<{ speed: Double }>;
|
|
36
37
|
onIsLoadingChanged?: DirectEventHandler<{ isLoading: boolean }>;
|
|
37
38
|
onError?: DirectEventHandler<ErrorEvent>;
|
|
39
|
+
onAccessTokenExpired?: DirectEventHandler<{ videoId: string }>;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
interface TPStreamsPlayerViewCommands {
|
|
@@ -56,6 +58,10 @@ interface TPStreamsPlayerViewCommands {
|
|
|
56
58
|
getPlaybackSpeed: (
|
|
57
59
|
viewRef: React.ElementRef<HostComponent<NativeProps>>
|
|
58
60
|
) => void;
|
|
61
|
+
setNewAccessToken: (
|
|
62
|
+
viewRef: React.ElementRef<HostComponent<NativeProps>>,
|
|
63
|
+
newToken: string
|
|
64
|
+
) => void;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
export const Commands = codegenNativeCommands<TPStreamsPlayerViewCommands>({
|
|
@@ -68,6 +74,7 @@ export const Commands = codegenNativeCommands<TPStreamsPlayerViewCommands>({
|
|
|
68
74
|
'getDuration',
|
|
69
75
|
'isPlaying',
|
|
70
76
|
'getPlaybackSpeed',
|
|
77
|
+
'setNewAccessToken',
|
|
71
78
|
],
|
|
72
79
|
});
|
|
73
80
|
|
package/lib/module/index.js
CHANGED
|
@@ -7,7 +7,7 @@ export * from './TPStreamsPlayerViewNativeComponent';
|
|
|
7
7
|
|
|
8
8
|
// Export the wrapper component as TPStreamsPlayerView
|
|
9
9
|
export { default as TPStreamsPlayerView } from "./TPStreamsPlayer.js";
|
|
10
|
-
export { pauseDownload, resumeDownload, removeDownload, isDownloaded, isDownloading, isPaused, getDownloadStatus, getAllDownloads } from "./TPStreamsDownload.js";
|
|
10
|
+
export { pauseDownload, resumeDownload, removeDownload, isDownloaded, isDownloading, isPaused, getDownloadStatus, getAllDownloads, addDownloadProgressListener, removeDownloadProgressListener, onDownloadProgressChanged } from "./TPStreamsDownload.js";
|
|
11
11
|
const TPStreamsModule = NativeModules.TPStreams;
|
|
12
12
|
export const TPStreams = {
|
|
13
13
|
initialize: organizationId => {
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","default","TPStreamsPlayerNative","TPStreamsPlayerView","pauseDownload","resumeDownload","removeDownload","isDownloaded","isDownloading","isPaused","getDownloadStatus","getAllDownloads","TPStreamsModule","TPStreams","initialize","organizationId"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,aAAa,QAAQ,cAAc;AAC5C;AACA,SAASC,OAAO,IAAIC,qBAAqB,QAAQ,sCAAsC;AACvF,cAAc,sCAAsC;;AAEpD;AACA,SAASD,OAAO,IAAIE,mBAAmB,QAAQ,sBAAmB;AAGlE,SACEC,aAAa,EACbC,cAAc,EACdC,cAAc,EACdC,YAAY,EACZC,aAAa,EACbC,QAAQ,EACRC,iBAAiB,EACjBC,eAAe,
|
|
1
|
+
{"version":3,"names":["NativeModules","default","TPStreamsPlayerNative","TPStreamsPlayerView","pauseDownload","resumeDownload","removeDownload","isDownloaded","isDownloading","isPaused","getDownloadStatus","getAllDownloads","addDownloadProgressListener","removeDownloadProgressListener","onDownloadProgressChanged","TPStreamsModule","TPStreams","initialize","organizationId"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,aAAa,QAAQ,cAAc;AAC5C;AACA,SAASC,OAAO,IAAIC,qBAAqB,QAAQ,sCAAsC;AACvF,cAAc,sCAAsC;;AAEpD;AACA,SAASD,OAAO,IAAIE,mBAAmB,QAAQ,sBAAmB;AAGlE,SACEC,aAAa,EACbC,cAAc,EACdC,cAAc,EACdC,YAAY,EACZC,aAAa,EACbC,QAAQ,EACRC,iBAAiB,EACjBC,eAAe,EACfC,2BAA2B,EAC3BC,8BAA8B,EAC9BC,yBAAyB,QAIpB,wBAAqB;AAE5B,MAAMC,eAAe,GAAGf,aAAa,CAACgB,SAAS;AAE/C,OAAO,MAAMA,SAAS,GAAG;EACvBC,UAAU,EAAGC,cAAsB,IAAW;IAC5CH,eAAe,CAACE,UAAU,CAACC,cAAc,CAAC;EAC5C;AACF,CAAC","ignoreList":[]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { EmitterSubscription } from 'react-native';
|
|
1
2
|
export interface DownloadItem {
|
|
2
3
|
videoId: string;
|
|
3
4
|
title: string;
|
|
@@ -6,7 +7,13 @@ export interface DownloadItem {
|
|
|
6
7
|
downloadedBytes: number;
|
|
7
8
|
progressPercentage: number;
|
|
8
9
|
state: string;
|
|
10
|
+
metadata: string;
|
|
9
11
|
}
|
|
12
|
+
export type DownloadProgressChange = DownloadItem;
|
|
13
|
+
export type DownloadProgressListener = (downloads: DownloadProgressChange[]) => void;
|
|
14
|
+
export declare function addDownloadProgressListener(): Promise<void>;
|
|
15
|
+
export declare function removeDownloadProgressListener(): Promise<void>;
|
|
16
|
+
export declare function onDownloadProgressChanged(listener: DownloadProgressListener): EmitterSubscription;
|
|
10
17
|
export declare function pauseDownload(videoId: string): Promise<void>;
|
|
11
18
|
export declare function resumeDownload(videoId: string): Promise<void>;
|
|
12
19
|
export declare function removeDownload(videoId: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TPStreamsDownload.d.ts","sourceRoot":"","sources":["../../../src/TPStreamsDownload.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TPStreamsDownload.d.ts","sourceRoot":"","sources":["../../../src/TPStreamsDownload.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,sBAAsB,GAAG,YAAY,CAAC;AAClD,MAAM,MAAM,wBAAwB,GAAG,CACrC,SAAS,EAAE,sBAAsB,EAAE,KAChC,IAAI,CAAC;AAIV,wBAAgB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3D;AAED,wBAAgB,8BAA8B,IAAI,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,wBAAwB,GACjC,mBAAmB,CAKrB;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE9D;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE/D;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAE1D;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAElE;AAED,wBAAgB,eAAe,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAEzD"}
|
|
@@ -17,6 +17,9 @@ export interface TPStreamsPlayerProps extends ViewProps {
|
|
|
17
17
|
startAt?: number;
|
|
18
18
|
enableDownload?: boolean;
|
|
19
19
|
showDefaultCaptions?: boolean;
|
|
20
|
+
downloadMetadata?: {
|
|
21
|
+
[key: string]: string;
|
|
22
|
+
};
|
|
20
23
|
onPlayerStateChanged?: (state: number) => void;
|
|
21
24
|
onIsPlayingChanged?: (isPlaying: boolean) => void;
|
|
22
25
|
onPlaybackSpeedChanged?: (speed: number) => void;
|
|
@@ -26,6 +29,7 @@ export interface TPStreamsPlayerProps extends ViewProps {
|
|
|
26
29
|
code: number;
|
|
27
30
|
details?: string;
|
|
28
31
|
}) => void;
|
|
32
|
+
onAccessTokenExpired?: (videoId: string, callback: (newToken: string) => void) => void;
|
|
29
33
|
}
|
|
30
34
|
/**
|
|
31
35
|
* TPStreamsPlayerView - React component wrapper for TPStreamsPlayerNative
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TPStreamsPlayer.d.ts","sourceRoot":"","sources":["../../../src/TPStreamsPlayer.tsx"],"names":[],"mappings":";AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAc9C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,kBAAkB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,gBAAgB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACzC;AAGD,MAAM,WAAW,oBAAqB,SAAQ,SAAS;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"TPStreamsPlayer.d.ts","sourceRoot":"","sources":["../../../src/TPStreamsPlayer.tsx"],"names":[],"mappings":";AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAc9C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,kBAAkB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1C,WAAW,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACnC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,gBAAgB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CACzC;AAGD,MAAM,WAAW,oBAAqB,SAAQ,SAAS;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAC7C,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,kBAAkB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,KAAK,IAAI,CAAC;IACX,oBAAoB,CAAC,EAAE,CACrB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,KACjC,IAAI,CAAC;CACX;AAED;;;GAGG;AACH,QAAA,MAAM,mBAAmB,qHAoMvB,CAAC;AAEH,eAAe,mBAAmB,CAAC"}
|
|
@@ -16,6 +16,7 @@ export interface NativeProps extends ViewProps {
|
|
|
16
16
|
startAt?: Double;
|
|
17
17
|
enableDownload?: boolean;
|
|
18
18
|
showDefaultCaptions?: boolean;
|
|
19
|
+
downloadMetadata?: string;
|
|
19
20
|
onCurrentPosition?: DirectEventHandler<{
|
|
20
21
|
position: Double;
|
|
21
22
|
}>;
|
|
@@ -41,6 +42,9 @@ export interface NativeProps extends ViewProps {
|
|
|
41
42
|
isLoading: boolean;
|
|
42
43
|
}>;
|
|
43
44
|
onError?: DirectEventHandler<ErrorEvent>;
|
|
45
|
+
onAccessTokenExpired?: DirectEventHandler<{
|
|
46
|
+
videoId: string;
|
|
47
|
+
}>;
|
|
44
48
|
}
|
|
45
49
|
interface TPStreamsPlayerViewCommands {
|
|
46
50
|
play: (viewRef: React.ElementRef<HostComponent<NativeProps>>) => void;
|
|
@@ -51,6 +55,7 @@ interface TPStreamsPlayerViewCommands {
|
|
|
51
55
|
getDuration: (viewRef: React.ElementRef<HostComponent<NativeProps>>) => void;
|
|
52
56
|
isPlaying: (viewRef: React.ElementRef<HostComponent<NativeProps>>) => void;
|
|
53
57
|
getPlaybackSpeed: (viewRef: React.ElementRef<HostComponent<NativeProps>>) => void;
|
|
58
|
+
setNewAccessToken: (viewRef: React.ElementRef<HostComponent<NativeProps>>, newToken: string) => void;
|
|
54
59
|
}
|
|
55
60
|
export declare const Commands: TPStreamsPlayerViewCommands;
|
|
56
61
|
declare const _default: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeProps>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TPStreamsPlayerViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/TPStreamsPlayerViewNativeComponent.ts"],"names":[],"mappings":";;AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACV,MAAM,EACN,KAAK,EACL,KAAK,EACN,MAAM,2CAA2C,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAGpF,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"TPStreamsPlayerViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/TPStreamsPlayerViewNativeComponent.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ export { default as TPStreamsPlayerNative } from './TPStreamsPlayerViewNativeCom
|
|
|
2
2
|
export * from './TPStreamsPlayerViewNativeComponent';
|
|
3
3
|
export { default as TPStreamsPlayerView } from './TPStreamsPlayer';
|
|
4
4
|
export type { TPStreamsPlayerRef } from './TPStreamsPlayer';
|
|
5
|
-
export { pauseDownload, resumeDownload, removeDownload, isDownloaded, isDownloading, isPaused, getDownloadStatus, getAllDownloads, type DownloadItem, } from './TPStreamsDownload';
|
|
5
|
+
export { pauseDownload, resumeDownload, removeDownload, isDownloaded, isDownloading, isPaused, getDownloadStatus, getAllDownloads, addDownloadProgressListener, removeDownloadProgressListener, onDownloadProgressChanged, type DownloadItem, type DownloadProgressChange, type DownloadProgressListener, } from './TPStreamsDownload';
|
|
6
6
|
export declare const TPStreams: {
|
|
7
7
|
initialize: (organizationId: string) => void;
|
|
8
8
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AACxF,cAAc,sCAAsC,CAAC;AAGrD,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACnE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EACL,aAAa,EACb,cAAc,EACd,cAAc,EACd,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,iBAAiB,EACjB,eAAe,EACf,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AACxF,cAAc,sCAAsC,CAAC;AAGrD,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACnE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,OAAO,EACL,aAAa,EACb,cAAc,EACd,cAAc,EACd,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,iBAAiB,EACjB,eAAe,EACf,2BAA2B,EAC3B,8BAA8B,EAC9B,yBAAyB,EACzB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,GAC9B,MAAM,qBAAqB,CAAC;AAI7B,eAAO,MAAM,SAAS;iCACS,MAAM,KAAG,IAAI;CAG3C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { NativeModules } from 'react-native';
|
|
1
|
+
import { NativeModules, NativeEventEmitter } from 'react-native';
|
|
2
|
+
import type { EmitterSubscription } from 'react-native';
|
|
2
3
|
|
|
3
4
|
const { TPStreamsDownload } = NativeModules;
|
|
4
5
|
|
|
@@ -10,6 +11,31 @@ export interface DownloadItem {
|
|
|
10
11
|
downloadedBytes: number;
|
|
11
12
|
progressPercentage: number;
|
|
12
13
|
state: string;
|
|
14
|
+
metadata: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type DownloadProgressChange = DownloadItem;
|
|
18
|
+
export type DownloadProgressListener = (
|
|
19
|
+
downloads: DownloadProgressChange[]
|
|
20
|
+
) => void;
|
|
21
|
+
|
|
22
|
+
const downloadEventEmitter = new NativeEventEmitter(TPStreamsDownload);
|
|
23
|
+
|
|
24
|
+
export function addDownloadProgressListener(): Promise<void> {
|
|
25
|
+
return TPStreamsDownload.addDownloadProgressListener();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function removeDownloadProgressListener(): Promise<void> {
|
|
29
|
+
return TPStreamsDownload.removeDownloadProgressListener();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function onDownloadProgressChanged(
|
|
33
|
+
listener: DownloadProgressListener
|
|
34
|
+
): EmitterSubscription {
|
|
35
|
+
return downloadEventEmitter.addListener(
|
|
36
|
+
'onDownloadProgressChanged',
|
|
37
|
+
listener
|
|
38
|
+
);
|
|
13
39
|
}
|
|
14
40
|
|
|
15
41
|
export function pauseDownload(videoId: string): Promise<void> {
|
package/src/TPStreamsPlayer.tsx
CHANGED
|
@@ -39,6 +39,7 @@ export interface TPStreamsPlayerProps extends ViewProps {
|
|
|
39
39
|
startAt?: number;
|
|
40
40
|
enableDownload?: boolean;
|
|
41
41
|
showDefaultCaptions?: boolean;
|
|
42
|
+
downloadMetadata?: { [key: string]: string };
|
|
42
43
|
onPlayerStateChanged?: (state: number) => void;
|
|
43
44
|
onIsPlayingChanged?: (isPlaying: boolean) => void;
|
|
44
45
|
onPlaybackSpeedChanged?: (speed: number) => void;
|
|
@@ -48,6 +49,10 @@ export interface TPStreamsPlayerProps extends ViewProps {
|
|
|
48
49
|
code: number;
|
|
49
50
|
details?: string;
|
|
50
51
|
}) => void;
|
|
52
|
+
onAccessTokenExpired?: (
|
|
53
|
+
videoId: string,
|
|
54
|
+
callback: (newToken: string) => void
|
|
55
|
+
) => void;
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
/**
|
|
@@ -65,12 +70,14 @@ const TPStreamsPlayerView = forwardRef<
|
|
|
65
70
|
startAt,
|
|
66
71
|
enableDownload,
|
|
67
72
|
showDefaultCaptions,
|
|
73
|
+
downloadMetadata,
|
|
68
74
|
style,
|
|
69
75
|
onPlayerStateChanged,
|
|
70
76
|
onIsPlayingChanged,
|
|
71
77
|
onPlaybackSpeedChanged,
|
|
72
78
|
onIsLoadingChanged,
|
|
73
79
|
onError,
|
|
80
|
+
onAccessTokenExpired,
|
|
74
81
|
...restProps
|
|
75
82
|
} = props;
|
|
76
83
|
|
|
@@ -160,6 +167,22 @@ const TPStreamsPlayerView = forwardRef<
|
|
|
160
167
|
[onError]
|
|
161
168
|
);
|
|
162
169
|
|
|
170
|
+
const handleAccessTokenExpired = useCallback(
|
|
171
|
+
(event: { nativeEvent: { videoId: string } }) => {
|
|
172
|
+
if (onAccessTokenExpired) {
|
|
173
|
+
const { videoId: expiredVideoId } = event.nativeEvent;
|
|
174
|
+
onAccessTokenExpired(expiredVideoId, (newToken: string) => {
|
|
175
|
+
if (nativeRef.current) {
|
|
176
|
+
Commands.setNewAccessToken(nativeRef.current, newToken);
|
|
177
|
+
} else {
|
|
178
|
+
console.error('[RN] Native ref is not available');
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
[onAccessTokenExpired]
|
|
184
|
+
);
|
|
185
|
+
|
|
163
186
|
// Helper to create promise-based API methods
|
|
164
187
|
const createPromiseMethod = useCallback(
|
|
165
188
|
(command: (ref: any) => void, eventKey: string) => {
|
|
@@ -215,6 +238,9 @@ const TPStreamsPlayerView = forwardRef<
|
|
|
215
238
|
startAt,
|
|
216
239
|
enableDownload,
|
|
217
240
|
showDefaultCaptions,
|
|
241
|
+
downloadMetadata: downloadMetadata
|
|
242
|
+
? JSON.stringify(downloadMetadata)
|
|
243
|
+
: undefined,
|
|
218
244
|
style,
|
|
219
245
|
onCurrentPosition,
|
|
220
246
|
onDuration,
|
|
@@ -225,6 +251,7 @@ const TPStreamsPlayerView = forwardRef<
|
|
|
225
251
|
onPlaybackSpeedChanged: handlePlaybackSpeedChanged,
|
|
226
252
|
onIsLoadingChanged: handleIsLoadingChanged,
|
|
227
253
|
onError: handleError,
|
|
254
|
+
onAccessTokenExpired: handleAccessTokenExpired,
|
|
228
255
|
};
|
|
229
256
|
|
|
230
257
|
return <TPStreamsPlayerNative {...nativeProps} ref={nativeRef} />;
|
|
@@ -22,6 +22,7 @@ export interface NativeProps extends ViewProps {
|
|
|
22
22
|
startAt?: Double;
|
|
23
23
|
enableDownload?: boolean;
|
|
24
24
|
showDefaultCaptions?: boolean;
|
|
25
|
+
downloadMetadata?: string;
|
|
25
26
|
|
|
26
27
|
// Event props for receiving data from native methods
|
|
27
28
|
onCurrentPosition?: DirectEventHandler<{ position: Double }>;
|
|
@@ -35,6 +36,7 @@ export interface NativeProps extends ViewProps {
|
|
|
35
36
|
onPlaybackSpeedChanged?: DirectEventHandler<{ speed: Double }>;
|
|
36
37
|
onIsLoadingChanged?: DirectEventHandler<{ isLoading: boolean }>;
|
|
37
38
|
onError?: DirectEventHandler<ErrorEvent>;
|
|
39
|
+
onAccessTokenExpired?: DirectEventHandler<{ videoId: string }>;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
interface TPStreamsPlayerViewCommands {
|
|
@@ -56,6 +58,10 @@ interface TPStreamsPlayerViewCommands {
|
|
|
56
58
|
getPlaybackSpeed: (
|
|
57
59
|
viewRef: React.ElementRef<HostComponent<NativeProps>>
|
|
58
60
|
) => void;
|
|
61
|
+
setNewAccessToken: (
|
|
62
|
+
viewRef: React.ElementRef<HostComponent<NativeProps>>,
|
|
63
|
+
newToken: string
|
|
64
|
+
) => void;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
export const Commands = codegenNativeCommands<TPStreamsPlayerViewCommands>({
|
|
@@ -68,6 +74,7 @@ export const Commands = codegenNativeCommands<TPStreamsPlayerViewCommands>({
|
|
|
68
74
|
'getDuration',
|
|
69
75
|
'isPlaying',
|
|
70
76
|
'getPlaybackSpeed',
|
|
77
|
+
'setNewAccessToken',
|
|
71
78
|
],
|
|
72
79
|
});
|
|
73
80
|
|
package/src/index.tsx
CHANGED
|
@@ -16,7 +16,12 @@ export {
|
|
|
16
16
|
isPaused,
|
|
17
17
|
getDownloadStatus,
|
|
18
18
|
getAllDownloads,
|
|
19
|
+
addDownloadProgressListener,
|
|
20
|
+
removeDownloadProgressListener,
|
|
21
|
+
onDownloadProgressChanged,
|
|
19
22
|
type DownloadItem,
|
|
23
|
+
type DownloadProgressChange,
|
|
24
|
+
type DownloadProgressListener,
|
|
20
25
|
} from './TPStreamsDownload';
|
|
21
26
|
|
|
22
27
|
const TPStreamsModule = NativeModules.TPStreams;
|