react-native-unified-player 0.3.10 → 0.4.1
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 +4 -3
- package/android/src/main/java/com/unifiedplayer/UnifiedPlayerEventEmitter.kt +2 -1
- package/android/src/main/java/com/unifiedplayer/UnifiedPlayerModule.kt +26 -0
- package/android/src/main/java/com/unifiedplayer/UnifiedPlayerView.kt +126 -1
- package/android/src/main/java/com/unifiedplayer/UnifiedPlayerViewManager.kt +6 -0
- package/ios/UnifiedPlayerModule.m +19 -0
- package/ios/UnifiedPlayerUIView.h +3 -0
- package/ios/UnifiedPlayerViewManager.m +138 -0
- package/lib/module/index.js +21 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/index.d.ts +9 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.tsx +44 -0
package/README.md
CHANGED
|
@@ -82,13 +82,14 @@ export default MyPlayerComponent;
|
|
|
82
82
|
|
|
83
83
|
| Prop | Type | Required | Description |
|
|
84
84
|
|------|------|----------|-------------|
|
|
85
|
-
| `videoUrl` | `string` | Yes | Video source URL |
|
|
85
|
+
| `videoUrl` | `string` \| `string[]` | Yes | Video source URL or an array of URLs for a playlist. |
|
|
86
86
|
| `style` | `ViewStyle` | Yes | Apply custom styling |
|
|
87
87
|
| `autoplay` | `boolean` | No | Autoplay video when loaded |
|
|
88
|
-
| `loop` | `boolean` | No | Should video loop when finished |
|
|
88
|
+
| `loop` | `boolean` | No | Should the video/playlist loop when finished. **Note:** Playlist advancement and looping are handled in the JavaScript layer via the `onPlaybackComplete` callback. The native player only loops single videos based on this prop. |
|
|
89
|
+
| `onLoadStart` | `(event: { nativeEvent?: { index?: number } }) => void` | No | Callback when video begins loading. The `event.nativeEvent` may contain an `index` property on Android when playing a playlist. |
|
|
89
90
|
| `onReadyToPlay` | `() => void` | No | Callback when video is ready to play |
|
|
90
91
|
| `onError` | `(error: any) => void` | No | Callback when an error occurs |
|
|
91
|
-
| `onPlaybackComplete` | `() => void` | No | Callback when video playback finishes |
|
|
92
|
+
| `onPlaybackComplete` | `() => void` | No | Callback when video playback finishes. Use this callback to implement playlist advancement logic in your JavaScript code. |
|
|
92
93
|
| `onProgress` | `(data: { currentTime: number; duration: number }) => void` | No | Callback for playback progress |
|
|
93
94
|
|
|
94
95
|
## Events
|
|
@@ -21,7 +21,8 @@ class UnifiedPlayerEventEmitter(private val reactContext: ReactApplicationContex
|
|
|
21
21
|
const val EVENT_RESUMED = "onPlaybackResumed"
|
|
22
22
|
const val EVENT_PLAYING = "onPlaying"
|
|
23
23
|
const val EVENT_PAUSED = "onPaused"
|
|
24
|
-
|
|
24
|
+
const val EVENT_FULLSCREEN_CHANGED = "onFullscreenChanged"
|
|
25
|
+
|
|
25
26
|
// Singleton instance for access from other classes
|
|
26
27
|
private var instance: UnifiedPlayerEventEmitter? = null
|
|
27
28
|
|
|
@@ -238,6 +238,32 @@ class UnifiedPlayerModule(private val reactContext: ReactApplicationContext) : R
|
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
+
@ReactMethod
|
|
242
|
+
fun toggleFullscreen(viewTag: Int, isFullscreen: Boolean, promise: Promise) {
|
|
243
|
+
Log.d(TAG, "Native toggleFullscreen method called with viewTag: $viewTag, isFullscreen: $isFullscreen")
|
|
244
|
+
try {
|
|
245
|
+
val playerView = getPlayerViewByTag(viewTag)
|
|
246
|
+
if (playerView != null) {
|
|
247
|
+
UiThreadUtil.runOnUiThread {
|
|
248
|
+
try {
|
|
249
|
+
playerView.setIsFullscreen(isFullscreen)
|
|
250
|
+
Log.d(TAG, "toggleFullscreen executed successfully")
|
|
251
|
+
promise.resolve(true)
|
|
252
|
+
} catch (e: Exception) {
|
|
253
|
+
Log.e(TAG, "Error toggling fullscreen: ${e.message}", e)
|
|
254
|
+
promise.reject("FULLSCREEN_ERROR", "Error toggling fullscreen: ${e.message}", e)
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
Log.e(TAG, "Player view not found for tag: $viewTag")
|
|
259
|
+
promise.reject("VIEW_NOT_FOUND", "Player view not found for tag: $viewTag")
|
|
260
|
+
}
|
|
261
|
+
} catch (e: Exception) {
|
|
262
|
+
Log.e(TAG, "Error in toggleFullscreen method: ${e.message}", e)
|
|
263
|
+
promise.reject("FULLSCREEN_ERROR", "Error in toggleFullscreen method: ${e.message}", e)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
241
267
|
@ReactMethod
|
|
242
268
|
fun stopRecording(viewTag: Int, promise: Promise) {
|
|
243
269
|
Log.d(TAG, "Native stopRecording method called with viewTag: $viewTag")
|
|
@@ -2,6 +2,8 @@ package com.unifiedplayer
|
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.content.Context
|
|
5
|
+
import android.app.Activity
|
|
6
|
+
import android.content.pm.ActivityInfo
|
|
5
7
|
import android.graphics.Bitmap
|
|
6
8
|
import android.graphics.Canvas
|
|
7
9
|
import android.graphics.Color
|
|
@@ -13,6 +15,7 @@ import android.os.Handler
|
|
|
13
15
|
import android.os.Looper
|
|
14
16
|
import android.view.Gravity
|
|
15
17
|
import android.view.View
|
|
18
|
+
import android.view.Surface
|
|
16
19
|
import android.widget.FrameLayout
|
|
17
20
|
import android.widget.ImageView
|
|
18
21
|
import com.bumptech.glide.Glide
|
|
@@ -35,7 +38,6 @@ import android.media.MediaCodec
|
|
|
35
38
|
import android.media.MediaCodecInfo
|
|
36
39
|
import android.media.MediaFormat
|
|
37
40
|
import android.media.MediaMuxer
|
|
38
|
-
import android.view.Surface
|
|
39
41
|
import java.nio.ByteBuffer
|
|
40
42
|
import android.os.Environment
|
|
41
43
|
import com.unifiedplayer.UnifiedPlayerEventEmitter.Companion.EVENT_COMPLETE
|
|
@@ -47,6 +49,10 @@ import com.unifiedplayer.UnifiedPlayerEventEmitter.Companion.EVENT_PROGRESS
|
|
|
47
49
|
import com.unifiedplayer.UnifiedPlayerEventEmitter.Companion.EVENT_READY
|
|
48
50
|
import com.unifiedplayer.UnifiedPlayerEventEmitter.Companion.EVENT_RESUMED
|
|
49
51
|
import com.unifiedplayer.UnifiedPlayerEventEmitter.Companion.EVENT_STALLED
|
|
52
|
+
import com.unifiedplayer.UnifiedPlayerEventEmitter.Companion.EVENT_FULLSCREEN_CHANGED
|
|
53
|
+
import android.view.ViewGroup
|
|
54
|
+
import android.view.WindowManager
|
|
55
|
+
import android.os.Build
|
|
50
56
|
|
|
51
57
|
class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
52
58
|
// Recording related variables
|
|
@@ -75,6 +81,13 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
75
81
|
internal var player: ExoPlayer? = null
|
|
76
82
|
private var currentProgress = 0
|
|
77
83
|
private var isPaused = false
|
|
84
|
+
private var isFullscreen = false
|
|
85
|
+
private var originalOrientation: Int = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
|
86
|
+
private var originalSystemUiVisibility: Int = 0
|
|
87
|
+
private var originalLayoutParams: ViewGroup.LayoutParams? = null
|
|
88
|
+
private var originalParent: ViewGroup? = null
|
|
89
|
+
private var originalIndex: Int = 0
|
|
90
|
+
private var fullscreenContainer: ViewGroup? = null
|
|
78
91
|
|
|
79
92
|
private val progressHandler = Handler(Looper.getMainLooper())
|
|
80
93
|
private val progressRunnable: Runnable = object : Runnable {
|
|
@@ -406,6 +419,117 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
406
419
|
}
|
|
407
420
|
}
|
|
408
421
|
|
|
422
|
+
fun setIsFullscreen(fullscreen: Boolean) {
|
|
423
|
+
Log.d(TAG, "setIsFullscreen called with value: $fullscreen")
|
|
424
|
+
if (this.isFullscreen == fullscreen) {
|
|
425
|
+
return // Already in the requested state
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
this.isFullscreen = fullscreen
|
|
429
|
+
val reactContext = context as? ReactContext ?: return
|
|
430
|
+
val activity = reactContext.currentActivity ?: return
|
|
431
|
+
|
|
432
|
+
// Alternative approach: Override the manifest setting temporarily
|
|
433
|
+
if (fullscreen) {
|
|
434
|
+
// Clear any portrait lock from manifest before entering fullscreen
|
|
435
|
+
overrideOrientationRestrictions(activity, true)
|
|
436
|
+
enterFullscreen(activity)
|
|
437
|
+
} else {
|
|
438
|
+
exitFullscreen(activity)
|
|
439
|
+
// Restore portrait lock after exiting fullscreen
|
|
440
|
+
overrideOrientationRestrictions(activity, false)
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Send event about fullscreen state change
|
|
444
|
+
val event = Arguments.createMap()
|
|
445
|
+
event.putBoolean("isFullscreen", fullscreen)
|
|
446
|
+
sendEvent(EVENT_FULLSCREEN_CHANGED, event)
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Override orientation restrictions from manifest
|
|
451
|
+
* This is a workaround for when android:screenOrientation="portrait" is set in manifest
|
|
452
|
+
*/
|
|
453
|
+
private fun overrideOrientationRestrictions(activity: Activity, enableLandscape: Boolean) {
|
|
454
|
+
try {
|
|
455
|
+
if (enableLandscape) {
|
|
456
|
+
// First set to unspecified to clear any manifest restrictions
|
|
457
|
+
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
|
458
|
+
// Small delay to ensure the change takes effect
|
|
459
|
+
Handler(Looper.getMainLooper()).postDelayed({
|
|
460
|
+
// Then set to sensor landscape
|
|
461
|
+
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
|
|
462
|
+
}, 50)
|
|
463
|
+
} else {
|
|
464
|
+
// Restore portrait orientation
|
|
465
|
+
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
|
466
|
+
}
|
|
467
|
+
} catch (e: Exception) {
|
|
468
|
+
Log.e(TAG, "Failed to override orientation restrictions: ${e.message}")
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
private fun enterFullscreen(activity: Activity) {
|
|
473
|
+
Log.d(TAG, "Entering fullscreen mode")
|
|
474
|
+
|
|
475
|
+
// Save current orientation
|
|
476
|
+
originalOrientation = activity.requestedOrientation
|
|
477
|
+
|
|
478
|
+
// Note: Orientation change is already handled by overrideOrientationRestrictions()
|
|
479
|
+
// in setIsFullscreen() before this method is called
|
|
480
|
+
|
|
481
|
+
// Hide system UI for fullscreen
|
|
482
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
483
|
+
activity.window.insetsController?.let { controller ->
|
|
484
|
+
controller.hide(android.view.WindowInsets.Type.statusBars())
|
|
485
|
+
controller.hide(android.view.WindowInsets.Type.navigationBars())
|
|
486
|
+
controller.systemBarsBehavior = android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
|
487
|
+
}
|
|
488
|
+
} else {
|
|
489
|
+
@Suppress("DEPRECATION")
|
|
490
|
+
originalSystemUiVisibility = activity.window.decorView.systemUiVisibility
|
|
491
|
+
@Suppress("DEPRECATION")
|
|
492
|
+
activity.window.decorView.systemUiVisibility = (
|
|
493
|
+
android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
|
494
|
+
or android.view.View.SYSTEM_UI_FLAG_FULLSCREEN
|
|
495
|
+
or android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
|
496
|
+
or android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
497
|
+
or android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
|
498
|
+
or android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
|
499
|
+
)
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Add FLAG_KEEP_SCREEN_ON to prevent screen from turning off during playback
|
|
503
|
+
activity.window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
|
504
|
+
|
|
505
|
+
// Simply inform React Native that we want fullscreen
|
|
506
|
+
// The React Native side should handle hiding other UI elements
|
|
507
|
+
Log.d(TAG, "Fullscreen mode activated - orientation changed to landscape")
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
private fun exitFullscreen(activity: Activity) {
|
|
511
|
+
Log.d(TAG, "Exiting fullscreen mode")
|
|
512
|
+
|
|
513
|
+
// Note: Orientation restoration is already handled by overrideOrientationRestrictions()
|
|
514
|
+
// in setIsFullscreen() after this method is called
|
|
515
|
+
|
|
516
|
+
// Restore system UI
|
|
517
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
518
|
+
activity.window.insetsController?.let { controller ->
|
|
519
|
+
controller.show(android.view.WindowInsets.Type.statusBars())
|
|
520
|
+
controller.show(android.view.WindowInsets.Type.navigationBars())
|
|
521
|
+
}
|
|
522
|
+
} else {
|
|
523
|
+
@Suppress("DEPRECATION")
|
|
524
|
+
activity.window.decorView.systemUiVisibility = originalSystemUiVisibility
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Remove FLAG_KEEP_SCREEN_ON
|
|
528
|
+
activity.window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
|
529
|
+
|
|
530
|
+
Log.d(TAG, "Fullscreen mode exited - orientation restored")
|
|
531
|
+
}
|
|
532
|
+
|
|
409
533
|
fun play() {
|
|
410
534
|
Log.d(TAG, "Play method called")
|
|
411
535
|
player?.playWhenReady = true
|
|
@@ -472,6 +596,7 @@ class UnifiedPlayerView(context: Context) : FrameLayout(context) {
|
|
|
472
596
|
EVENT_PLAYING -> "topPlaying"
|
|
473
597
|
EVENT_PAUSED -> "topPlaybackPaused"
|
|
474
598
|
EVENT_LOAD_START -> "topLoadStart"
|
|
599
|
+
EVENT_FULLSCREEN_CHANGED -> "topFullscreenChanged"
|
|
475
600
|
else -> "top${eventName.substring(2)}" // Fallback for any other events
|
|
476
601
|
}
|
|
477
602
|
|
|
@@ -75,6 +75,11 @@ class UnifiedPlayerViewManager : SimpleViewManager<UnifiedPlayerView>() {
|
|
|
75
75
|
view.setIsPaused(isPaused)
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
@ReactProp(name = "isFullscreen")
|
|
79
|
+
fun setIsFullscreen(view: UnifiedPlayerView, isFullscreen: Boolean) {
|
|
80
|
+
view.setIsFullscreen(isFullscreen)
|
|
81
|
+
}
|
|
82
|
+
|
|
78
83
|
|
|
79
84
|
|
|
80
85
|
// Register direct events
|
|
@@ -92,6 +97,7 @@ class UnifiedPlayerViewManager : SimpleViewManager<UnifiedPlayerView>() {
|
|
|
92
97
|
.put("topPlaybackPaused", MapBuilder.of("registrationName", "onPaused"))
|
|
93
98
|
.put("topPlaying", MapBuilder.of("registrationName", "onPlaying"))
|
|
94
99
|
.put("topLoadStart", MapBuilder.of("registrationName", "onLoadStart"))
|
|
100
|
+
.put("topFullscreenChanged", MapBuilder.of("registrationName", "onFullscreenChanged"))
|
|
95
101
|
.build()
|
|
96
102
|
}
|
|
97
103
|
}
|
|
@@ -248,6 +248,25 @@ RCT_EXPORT_METHOD(startRecording:(nonnull NSNumber *)reactTag
|
|
|
248
248
|
}];
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
RCT_EXPORT_METHOD(toggleFullscreen:(nonnull NSNumber *)reactTag
|
|
252
|
+
isFullscreen:(BOOL)isFullscreen
|
|
253
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
254
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
255
|
+
{
|
|
256
|
+
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
257
|
+
UIView *view = viewRegistry[reactTag];
|
|
258
|
+
if (![view isKindOfClass:[UnifiedPlayerUIView class]]) {
|
|
259
|
+
RCTLogError(@"Invalid view returned from registry, expecting UnifiedPlayerUIView, got: %@", view);
|
|
260
|
+
reject(@"E_INVALID_VIEW", @"Expected UnifiedPlayerUIView", nil);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
UnifiedPlayerUIView *playerView = (UnifiedPlayerUIView *)view;
|
|
265
|
+
[playerView toggleFullscreen:isFullscreen];
|
|
266
|
+
resolve(@(YES));
|
|
267
|
+
}];
|
|
268
|
+
}
|
|
269
|
+
|
|
251
270
|
RCT_EXPORT_METHOD(stopRecording:(nonnull NSNumber *)reactTag
|
|
252
271
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
253
272
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
@@ -18,6 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
18
18
|
@property (nonatomic, assign) BOOL autoplay;
|
|
19
19
|
@property (nonatomic, assign) BOOL loop;
|
|
20
20
|
@property (nonatomic, assign) BOOL isPaused;
|
|
21
|
+
@property (nonatomic, assign) BOOL isFullscreen;
|
|
21
22
|
@property (nonatomic, strong) NSArray *mediaOptions;
|
|
22
23
|
@property (nonatomic, weak) RCTBridge *bridge;
|
|
23
24
|
@property (nonatomic, assign) VLCMediaPlayerState previousState;
|
|
@@ -41,8 +42,10 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
41
42
|
@property (nonatomic, copy) RCTDirectEventBlock onPlaybackResumed;
|
|
42
43
|
@property (nonatomic, copy) RCTDirectEventBlock onPlaying;
|
|
43
44
|
@property (nonatomic, copy) RCTDirectEventBlock onPaused;
|
|
45
|
+
@property (nonatomic, copy) RCTDirectEventBlock onFullscreenChanged;
|
|
44
46
|
|
|
45
47
|
// Method declarations
|
|
48
|
+
- (void)toggleFullscreen:(BOOL)fullscreen;
|
|
46
49
|
- (void)setupWithVideoUrlString:(nullable NSString *)videoUrlString;
|
|
47
50
|
- (void)setupWithVideoUrlArray:(NSArray<NSString *> *)urlArray; // New method for playlists
|
|
48
51
|
- (void)setupThumbnailWithUrlString:(nullable NSString *)thumbnailUrlString;
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
// Main player view implementation
|
|
15
15
|
@implementation UnifiedPlayerUIView {
|
|
16
16
|
UIImageView *_thumbnailImageView;
|
|
17
|
+
CGRect _originalFrame;
|
|
18
|
+
UIView *_originalSuperview;
|
|
19
|
+
NSUInteger _originalIndex;
|
|
20
|
+
UIView *_fullscreenContainer;
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
- (instancetype)init {
|
|
@@ -54,6 +58,7 @@
|
|
|
54
58
|
|
|
55
59
|
_autoplay = YES;
|
|
56
60
|
_loop = NO;
|
|
61
|
+
_isFullscreen = NO;
|
|
57
62
|
|
|
58
63
|
// Add notification for app entering background
|
|
59
64
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
@@ -738,6 +743,132 @@
|
|
|
738
743
|
}
|
|
739
744
|
}
|
|
740
745
|
|
|
746
|
+
- (void)setIsFullscreen:(BOOL)isFullscreen {
|
|
747
|
+
RCTLogInfo(@"[UnifiedPlayerViewManager] setIsFullscreen: %d", isFullscreen);
|
|
748
|
+
[self toggleFullscreen:isFullscreen];
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
- (void)toggleFullscreen:(BOOL)fullscreen {
|
|
752
|
+
if (_isFullscreen == fullscreen) {
|
|
753
|
+
return; // Already in the requested state
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
_isFullscreen = fullscreen;
|
|
757
|
+
|
|
758
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
759
|
+
if (fullscreen) {
|
|
760
|
+
[self enterFullscreen];
|
|
761
|
+
} else {
|
|
762
|
+
[self exitFullscreen];
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// Send event about fullscreen state change
|
|
766
|
+
if (self.onFullscreenChanged) {
|
|
767
|
+
self.onFullscreenChanged(@{@"isFullscreen": @(fullscreen)});
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
- (void)enterFullscreen {
|
|
773
|
+
RCTLogInfo(@"[UnifiedPlayerViewManager] Entering fullscreen mode");
|
|
774
|
+
|
|
775
|
+
// Get the key window
|
|
776
|
+
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
|
|
777
|
+
if (!keyWindow) {
|
|
778
|
+
RCTLogError(@"[UnifiedPlayerViewManager] Cannot find key window");
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// Save original frame and superview
|
|
783
|
+
_originalFrame = self.frame;
|
|
784
|
+
_originalSuperview = self.superview;
|
|
785
|
+
_originalIndex = [self.superview.subviews indexOfObject:self];
|
|
786
|
+
|
|
787
|
+
// Remove from current superview
|
|
788
|
+
[self removeFromSuperview];
|
|
789
|
+
|
|
790
|
+
// Add to window with fullscreen frame
|
|
791
|
+
CGRect fullscreenFrame = keyWindow.bounds;
|
|
792
|
+
self.frame = fullscreenFrame;
|
|
793
|
+
[keyWindow addSubview:self];
|
|
794
|
+
|
|
795
|
+
// Bring to front
|
|
796
|
+
[keyWindow bringSubviewToFront:self];
|
|
797
|
+
|
|
798
|
+
// Force landscape orientation
|
|
799
|
+
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
|
|
800
|
+
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
|
|
801
|
+
[UIViewController attemptRotationToDeviceOrientation];
|
|
802
|
+
|
|
803
|
+
// Hide status bar
|
|
804
|
+
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
|
|
805
|
+
|
|
806
|
+
// Keep screen on during playback
|
|
807
|
+
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
|
|
808
|
+
|
|
809
|
+
// Set background color to black for better fullscreen experience
|
|
810
|
+
self.backgroundColor = [UIColor blackColor];
|
|
811
|
+
|
|
812
|
+
// Update player layout
|
|
813
|
+
[self setNeedsLayout];
|
|
814
|
+
[self layoutIfNeeded];
|
|
815
|
+
|
|
816
|
+
// Re-attach the drawable to ensure video continues playing
|
|
817
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
818
|
+
if (_player) {
|
|
819
|
+
// Reset the drawable to ensure the video surface is properly connected
|
|
820
|
+
_player.drawable = nil;
|
|
821
|
+
_player.drawable = self;
|
|
822
|
+
RCTLogInfo(@"[UnifiedPlayerViewManager] Re-attached drawable after entering fullscreen");
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
- (void)exitFullscreen {
|
|
828
|
+
RCTLogInfo(@"[UnifiedPlayerViewManager] Exiting fullscreen mode");
|
|
829
|
+
|
|
830
|
+
// Remove from window
|
|
831
|
+
[self removeFromSuperview];
|
|
832
|
+
|
|
833
|
+
// Restore to original superview
|
|
834
|
+
if (_originalSuperview) {
|
|
835
|
+
self.frame = _originalFrame;
|
|
836
|
+
if (_originalIndex < _originalSuperview.subviews.count) {
|
|
837
|
+
[_originalSuperview insertSubview:self atIndex:_originalIndex];
|
|
838
|
+
} else {
|
|
839
|
+
[_originalSuperview addSubview:self];
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// Restore portrait orientation
|
|
844
|
+
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
|
|
845
|
+
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
|
|
846
|
+
[UIViewController attemptRotationToDeviceOrientation];
|
|
847
|
+
|
|
848
|
+
// Show status bar
|
|
849
|
+
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
|
|
850
|
+
|
|
851
|
+
// Allow screen to turn off
|
|
852
|
+
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
|
|
853
|
+
|
|
854
|
+
// Restore original background color
|
|
855
|
+
self.backgroundColor = [UIColor blackColor];
|
|
856
|
+
|
|
857
|
+
// Update player layout
|
|
858
|
+
[self setNeedsLayout];
|
|
859
|
+
[self layoutIfNeeded];
|
|
860
|
+
|
|
861
|
+
// Re-attach the drawable to ensure video continues playing
|
|
862
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
863
|
+
if (_player) {
|
|
864
|
+
// Reset the drawable to ensure the video surface is properly connected
|
|
865
|
+
_player.drawable = nil;
|
|
866
|
+
_player.drawable = self;
|
|
867
|
+
RCTLogInfo(@"[UnifiedPlayerViewManager] Re-attached drawable after exiting fullscreen");
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
}
|
|
871
|
+
|
|
741
872
|
|
|
742
873
|
#pragma mark - VLCMediaPlayerDelegate
|
|
743
874
|
|
|
@@ -1005,6 +1136,12 @@ RCT_CUSTOM_VIEW_PROPERTY(isPaused, BOOL, UnifiedPlayerUIView)
|
|
|
1005
1136
|
view.isPaused = [RCTConvert BOOL:json];
|
|
1006
1137
|
}
|
|
1007
1138
|
|
|
1139
|
+
// isFullscreen property
|
|
1140
|
+
RCT_CUSTOM_VIEW_PROPERTY(isFullscreen, BOOL, UnifiedPlayerUIView)
|
|
1141
|
+
{
|
|
1142
|
+
view.isFullscreen = [RCTConvert BOOL:json];
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1008
1145
|
// Event handlers
|
|
1009
1146
|
RCT_EXPORT_VIEW_PROPERTY(onLoadStart, RCTDirectEventBlock);
|
|
1010
1147
|
RCT_EXPORT_VIEW_PROPERTY(onReadyToPlay, RCTDirectEventBlock);
|
|
@@ -1015,5 +1152,6 @@ RCT_EXPORT_VIEW_PROPERTY(onPlaybackStalled, RCTDirectEventBlock);
|
|
|
1015
1152
|
RCT_EXPORT_VIEW_PROPERTY(onPlaybackResumed, RCTDirectEventBlock);
|
|
1016
1153
|
RCT_EXPORT_VIEW_PROPERTY(onPlaying, RCTDirectEventBlock);
|
|
1017
1154
|
RCT_EXPORT_VIEW_PROPERTY(onPaused, RCTDirectEventBlock);
|
|
1155
|
+
RCT_EXPORT_VIEW_PROPERTY(onFullscreenChanged, RCTDirectEventBlock);
|
|
1018
1156
|
|
|
1019
1157
|
@end
|
package/lib/module/index.js
CHANGED
|
@@ -185,6 +185,27 @@ export const UnifiedPlayer = {
|
|
|
185
185
|
return Promise.reject(error);
|
|
186
186
|
}
|
|
187
187
|
},
|
|
188
|
+
/**
|
|
189
|
+
* Toggle fullscreen mode
|
|
190
|
+
* @param viewTag - The tag of the player view
|
|
191
|
+
* @param isFullscreen - Whether to enter or exit fullscreen mode
|
|
192
|
+
* @returns Promise resolving to true if successful
|
|
193
|
+
*/
|
|
194
|
+
toggleFullscreen: (viewTag, isFullscreen) => {
|
|
195
|
+
try {
|
|
196
|
+
console.log('UnifiedPlayer.toggleFullscreen called with viewTag:', viewTag, 'isFullscreen:', isFullscreen);
|
|
197
|
+
return UnifiedPlayerModule.toggleFullscreen(viewTag, isFullscreen).then(result => {
|
|
198
|
+
console.log('Native toggleFullscreen method called successfully');
|
|
199
|
+
return result;
|
|
200
|
+
}).catch(error => {
|
|
201
|
+
console.log('Error calling toggleFullscreen:', error instanceof Error ? error.message : String(error));
|
|
202
|
+
throw error;
|
|
203
|
+
});
|
|
204
|
+
} catch (error) {
|
|
205
|
+
console.log('Error calling toggleFullscreen:', error instanceof Error ? error.message : String(error));
|
|
206
|
+
return Promise.reject(error);
|
|
207
|
+
}
|
|
208
|
+
},
|
|
188
209
|
/**
|
|
189
210
|
* Stop recording the video
|
|
190
211
|
* @param viewTag - The tag of the player view
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["forwardRef","requireNativeComponent","UIManager","NativeModules","Platform","jsx","_jsx","LINKING_ERROR","select","ios","default","getViewManagerConfig","UnifiedPlayer","Error","NativeUnifiedPlayerView","UnifiedPlayerModule","UnifiedPlayerEventTypes","LOAD_START","READY","ERROR","PROGRESS","COMPLETE","STALLED","RESUMED","PLAYING","PAUSED","UnifiedPlayerEvents","UnifiedPlayerView","props","ref","play","viewTag","console","log","then","result","catch","error","message","String","Promise","reject","pause","seekTo","time","getCurrentTime","getDuration","capture","base64String","startRecording","outputPath","stopRecording","filePath"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAA0BA,UAAU,QAAQ,OAAO,CAAC,CAAC;AACrD,SACEC,sBAAsB,EACtBC,SAAS,EACTC,aAAa,EACbC,QAAQ,QAEH,cAAc;;AAErB;AAAA,SAAAC,GAAA,IAAAC,IAAA;AACA,MAAMC,aAAa,GACjB,sFAAsF,GACtFH,QAAQ,CAACI,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;;AAEjC;AACA,IACE,CAACR,SAAS,CAACS,oBAAoB,CAAC,mBAAmB,CAAC,IACpD,CAACR,aAAa,CAACS,aAAa,EAC5B;EACA,MAAM,IAAIC,KAAK,CAACN,aAAa,CAAC;AAChC;;AAEA;;
|
|
1
|
+
{"version":3,"names":["forwardRef","requireNativeComponent","UIManager","NativeModules","Platform","jsx","_jsx","LINKING_ERROR","select","ios","default","getViewManagerConfig","UnifiedPlayer","Error","NativeUnifiedPlayerView","UnifiedPlayerModule","UnifiedPlayerEventTypes","LOAD_START","READY","ERROR","PROGRESS","COMPLETE","STALLED","RESUMED","PLAYING","PAUSED","UnifiedPlayerEvents","UnifiedPlayerView","props","ref","play","viewTag","console","log","then","result","catch","error","message","String","Promise","reject","pause","seekTo","time","getCurrentTime","getDuration","capture","base64String","startRecording","outputPath","toggleFullscreen","isFullscreen","stopRecording","filePath"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -22,6 +22,8 @@ export type UnifiedPlayerProps = {
|
|
|
22
22
|
onPlaybackResumed?: () => void;
|
|
23
23
|
onPaused?: () => void;
|
|
24
24
|
onPlaying?: () => void;
|
|
25
|
+
isFullscreen?: boolean;
|
|
26
|
+
onFullscreenChanged?: (isFullscreen: boolean) => void;
|
|
25
27
|
};
|
|
26
28
|
export declare const UnifiedPlayerEventTypes: {
|
|
27
29
|
LOAD_START: string;
|
|
@@ -87,6 +89,13 @@ export declare const UnifiedPlayer: {
|
|
|
87
89
|
* @returns Promise resolving to true if recording started successfully
|
|
88
90
|
*/
|
|
89
91
|
startRecording: (viewTag: number, outputPath?: string) => Promise<boolean>;
|
|
92
|
+
/**
|
|
93
|
+
* Toggle fullscreen mode
|
|
94
|
+
* @param viewTag - The tag of the player view
|
|
95
|
+
* @param isFullscreen - Whether to enter or exit fullscreen mode
|
|
96
|
+
* @returns Promise resolving to true if successful
|
|
97
|
+
*/
|
|
98
|
+
toggleFullscreen: (viewTag: number, isFullscreen: boolean) => Promise<boolean>;
|
|
90
99
|
/**
|
|
91
100
|
* Stop recording the video
|
|
92
101
|
* @param viewTag - The tag of the player view
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAkBtB,MAAM,MAAM,kBAAkB,GAAG;IAE/B,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAG5B,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,KAAK,EAAE,SAAS,CAAC;IAGjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,IAAI,CAAC,EAAE,OAAO,CAAC;IAGf,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAGpE,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAG3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAG/B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAGhC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAGvE,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAG/B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAG/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAGtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAkBtB,MAAM,MAAM,kBAAkB,GAAG;IAE/B,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAG5B,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,KAAK,EAAE,SAAS,CAAC;IAGjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,IAAI,CAAC,EAAE,OAAO,CAAC;IAGf,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,KAAK,IAAI,CAAC;IAGpE,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAG3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAG/B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAGhC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAGvE,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAG/B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAG/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IAGtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IAGvB,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,mBAAmB,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD,CAAC;AAYF,eAAO,MAAM,uBAAuB;;;;;;;;;;CAUnC,CAAC;AAGF,eAAO,MAAM,mBAAmB,KAA8B,CAAC;AAE/D;;GAEG;AACH,eAAO,MAAM,iBAAiB,8LAK5B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa;IACxB;;;;OAIG;oBACa,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;IAwBzC;;;;OAIG;qBACc,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;IAwB1C;;;;;OAKG;sBACe,MAAM,QAAQ,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;IA6BzD;;;;OAIG;8BACuB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;IAalD;;;;OAIG;2BACoB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;IAa/C;;;;OAIG;uBACgB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;IAwB3C;;;;;OAKG;8BACuB,MAAM,eAAe,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;IAwBxE;;;;;OAKG;gCAEQ,MAAM,gBACD,OAAO,KACpB,OAAO,CAAC,OAAO,CAAC;IA6BnB;;;;OAIG;6BACsB,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;CAuBlD,CAAC"}
|
package/package.json
CHANGED
package/src/index.tsx
CHANGED
|
@@ -68,6 +68,12 @@ export type UnifiedPlayerProps = {
|
|
|
68
68
|
|
|
69
69
|
// Callback when playback is playing
|
|
70
70
|
onPlaying?: () => void;
|
|
71
|
+
|
|
72
|
+
// Fullscreen mode - automatically rotates to landscape when true
|
|
73
|
+
isFullscreen?: boolean;
|
|
74
|
+
|
|
75
|
+
// Callback when fullscreen state changes
|
|
76
|
+
onFullscreenChanged?: (isFullscreen: boolean) => void;
|
|
71
77
|
};
|
|
72
78
|
|
|
73
79
|
// Native component registration
|
|
@@ -297,6 +303,44 @@ export const UnifiedPlayer = {
|
|
|
297
303
|
}
|
|
298
304
|
},
|
|
299
305
|
|
|
306
|
+
/**
|
|
307
|
+
* Toggle fullscreen mode
|
|
308
|
+
* @param viewTag - The tag of the player view
|
|
309
|
+
* @param isFullscreen - Whether to enter or exit fullscreen mode
|
|
310
|
+
* @returns Promise resolving to true if successful
|
|
311
|
+
*/
|
|
312
|
+
toggleFullscreen: (
|
|
313
|
+
viewTag: number,
|
|
314
|
+
isFullscreen: boolean
|
|
315
|
+
): Promise<boolean> => {
|
|
316
|
+
try {
|
|
317
|
+
console.log(
|
|
318
|
+
'UnifiedPlayer.toggleFullscreen called with viewTag:',
|
|
319
|
+
viewTag,
|
|
320
|
+
'isFullscreen:',
|
|
321
|
+
isFullscreen
|
|
322
|
+
);
|
|
323
|
+
return UnifiedPlayerModule.toggleFullscreen(viewTag, isFullscreen)
|
|
324
|
+
.then((result: boolean) => {
|
|
325
|
+
console.log('Native toggleFullscreen method called successfully');
|
|
326
|
+
return result;
|
|
327
|
+
})
|
|
328
|
+
.catch((error: any) => {
|
|
329
|
+
console.log(
|
|
330
|
+
'Error calling toggleFullscreen:',
|
|
331
|
+
error instanceof Error ? error.message : String(error)
|
|
332
|
+
);
|
|
333
|
+
throw error;
|
|
334
|
+
});
|
|
335
|
+
} catch (error) {
|
|
336
|
+
console.log(
|
|
337
|
+
'Error calling toggleFullscreen:',
|
|
338
|
+
error instanceof Error ? error.message : String(error)
|
|
339
|
+
);
|
|
340
|
+
return Promise.reject(error);
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
|
|
300
344
|
/**
|
|
301
345
|
* Stop recording the video
|
|
302
346
|
* @param viewTag - The tag of the player view
|