···18@@ -0,0 +1,2 @@
19+# Keep FullscreenActivity from being stripped by R8/ProGuard
20+-keep class expo.modules.blueskyvideo.FullscreenActivity { *; }
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
···18@@ -0,0 +1,2 @@
19+# Keep FullscreenActivity from being stripped by R8/ProGuard
20+-keep class expo.modules.blueskyvideo.FullscreenActivity { *; }
21+diff --git a/node_modules/@haileyok/bluesky-video/android/src/main/java/expo/modules/blueskyvideo/BlueskyVideoView.kt b/node_modules/@haileyok/bluesky-video/android/src/main/java/expo/modules/blueskyvideo/BlueskyVideoView.kt
22+index fdabd84..eda8c7c 100644
23+--- a/node_modules/@haileyok/bluesky-video/android/src/main/java/expo/modules/blueskyvideo/BlueskyVideoView.kt
24++++ b/node_modules/@haileyok/bluesky-video/android/src/main/java/expo/modules/blueskyvideo/BlueskyVideoView.kt
25+@@ -1,8 +1,11 @@
26+ package expo.modules.blueskyvideo
27+28++import android.app.Activity
29+ import android.content.Context
30+ import android.content.Intent
31+ import android.graphics.Color
32++import android.os.Build
33++import android.util.Log
34+ import android.graphics.Rect
35+ import android.net.Uri
36+ import android.view.ViewGroup
37+@@ -237,9 +240,44 @@ class BlueskyVideoView(
38+ // Fullscreen handling
39+40+ fun enterFullscreen(keepDisplayOn: Boolean) {
41+- val currentActivity = this.appContext.currentActivity ?: return
42++ val tag = "BlueskyVideo"
43++
44++ Log.d(tag, "enterFullscreen() called - keepDisplayOn=$keepDisplayOn")
45++ Log.d(tag, " isFullscreen=$isFullscreen, isPlaying=$isPlaying, isMuted=$isMuted")
46++ Log.d(tag, " player=${player != null}, url=$url")
47++ Log.d(tag, " isAttachedToWindow=$isAttachedToWindow, isShown=$isShown")
48++ Log.d(tag, " Android SDK: ${Build.VERSION.SDK_INT}, Device: ${Build.MANUFACTURER} ${Build.MODEL}")
49++
50++ val currentActivity = this.appContext.currentActivity
51++ if (currentActivity == null) {
52++ Log.e(tag, "enterFullscreen() FAILED: currentActivity is null")
53++ Log.e(tag, " appContext=$appContext")
54++ onError(mapOf("error" to "Cannot enter fullscreen: no current activity"))
55++ return
56++ }
57++
58++ Log.d(tag, " currentActivity=$currentActivity")
59++ Log.d(tag, " activity.isFinishing=${currentActivity.isFinishing}")
60++ Log.d(tag, " activity.isDestroyed=${currentActivity.isDestroyed}")
61++ Log.d(tag, " activity.lifecycle=${(currentActivity as? androidx.lifecycle.LifecycleOwner)?.lifecycle?.currentState}")
62++ Log.d(tag, " activity.hasWindowFocus=${currentActivity.hasWindowFocus()}")
63++ Log.d(tag, " activity.window.isActive=${currentActivity.window?.isActive}")
64++
65++ // Check if activity is in a valid state to start another activity
66++ if (currentActivity.isFinishing) {
67++ Log.e(tag, "enterFullscreen() FAILED: currentActivity is finishing")
68++ onError(mapOf("error" to "Cannot enter fullscreen: activity is finishing"))
69++ return
70++ }
71++
72++ if (currentActivity.isDestroyed) {
73++ Log.e(tag, "enterFullscreen() FAILED: currentActivity is destroyed")
74++ onError(mapOf("error" to "Cannot enter fullscreen: activity is destroyed"))
75++ return
76++ }
77+78+ this.enteredFullscreenMuteState = this.isMuted
79++ Log.d(tag, " saved enteredFullscreenMuteState=$enteredFullscreenMuteState")
80+81+ // We always want to start with unmuted state and playing. Fire those from here so the
82+ // event dispatcher gets called
83+@@ -247,18 +285,51 @@ class BlueskyVideoView(
84+ if (!this.isPlaying) {
85+ this.play()
86+ }
87++ Log.d(tag, " after unmute/play: isPlaying=$isPlaying, isMuted=$isMuted")
88+89+ // Remove the player from this view, but don't null the player!
90+ this.playerView.player = null
91++ Log.d(tag, " detached player from playerView")
92+93+ // create the intent and give it a view
94+ val intent = Intent(context, FullscreenActivity::class.java)
95+ intent.putExtra("keepDisplayOn", keepDisplayOn)
96+ FullscreenActivity.asscVideoView = WeakReference(this)
97+98++ Log.d(tag, " intent created: $intent")
99++ Log.d(tag, " intent.component=${intent.component}")
100++ Log.d(tag, " intent.flags=${intent.flags} (0x${Integer.toHexString(intent.flags)})")
101++ Log.d(tag, " context for intent=$context")
102++ Log.d(tag, " FullscreenActivity.asscVideoView set to WeakReference(this)")
103++
104+ // fire the fullscreen event and launch the intent
105+- this.isFullscreen = true
106+- currentActivity.startActivity(intent)
107++ try {
108++ Log.d(tag, " calling startActivity()...")
109++ currentActivity.startActivity(intent)
110++ this.isFullscreen = true
111++ Log.d(tag, " startActivity() SUCCESS - isFullscreen set to true")
112++ } catch (e: Exception) {
113++ Log.e(tag, "enterFullscreen() FAILED: startActivity() threw exception", e)
114++ Log.e(tag, " exception class: ${e.javaClass.name}")
115++ Log.e(tag, " exception message: ${e.message}")
116++ Log.e(tag, " exception cause: ${e.cause}")
117++ e.printStackTrace()
118++
119++ // Restore state since fullscreen failed
120++ this.playerView.player = this.player
121++ Log.d(tag, " restored player to playerView after failure")
122++
123++ if (this.enteredFullscreenMuteState) {
124++ this.mute()
125++ Log.d(tag, " restored mute state after failure")
126++ }
127++
128++ onError(mapOf(
129++ "error" to "Failed to enter fullscreen: ${e.message}",
130++ "exceptionClass" to e.javaClass.name,
131++ "exceptionMessage" to (e.message ?: "unknown")
132++ ))
133++ }
134+ }
135+136+ fun onExitFullscreen() {