react-native-spalla-player 0.13.4 → 0.14.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.
@@ -1,36 +1,62 @@
1
1
  package com.spallaplayer
2
2
 
3
3
  import android.content.Context
4
+ import android.util.Log
4
5
  import android.widget.FrameLayout
5
6
  import com.spalla.sdk.android.core.player.view.SpallaPlayerView
6
7
  import android.view.ViewGroup;
8
+ import androidx.core.view.isNotEmpty
7
9
 
8
10
  class SpallaPlayerContainerView(context: Context) : ViewGroup(context) {
9
- val spallaPlayerView: SpallaPlayerView = SpallaPlayerView(context)
11
+ val spallaPlayerView: SpallaPlayerView = SpallaPlayerView(context)
12
+ private var isAttachedToWindow = false
10
13
 
11
- init {
12
- addView(spallaPlayerView) // Add SpallaPlayerView as a child of this container
13
- // You might need to set layout params for spallaPlayerView here
14
- }
14
+ init {
15
+ addView(spallaPlayerView)
16
+ requestLayout()
17
+ }
18
+
19
+ override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
20
+ val containerWidth = r - l
21
+ val containerHeight = b - t
22
+
23
+ Log.d("SpallaPlayerContainerView", "Layout: container=${containerWidth}x${containerHeight}")
24
+
25
+ for (i in 0 until childCount) {
26
+ val child = getChildAt(i)
27
+ child.layout(0, 0, containerWidth, containerHeight)
15
28
 
16
- override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
17
- for (i in 0 until childCount) {
18
- val child = getChildAt(i)
19
- child.layout(0, 0, width, height)
29
+ if (child is SpallaPlayerView) {
30
+ // Schedule multiple layout passes to catch the async initialization
31
+ repeat(3) { index ->
32
+ child.post {
33
+ child.requestLayout()
34
+ }
35
+ }
36
+ }
37
+ }
20
38
  }
21
- }
22
39
 
23
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
24
- val width = MeasureSpec.getSize(widthMeasureSpec)
25
- val height = MeasureSpec.getSize(heightMeasureSpec)
26
- for (i in 0 until childCount) {
27
- val child = getChildAt(i)
28
- child.measure(
29
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
30
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
31
- )
40
+ override fun onAttachedToWindow() {
41
+ super.onAttachedToWindow()
42
+ isAttachedToWindow = true
43
+ // Ensure proper initialization when attached to window
44
+ post {
45
+ requestLayout()
46
+ }
47
+ }
48
+
49
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
50
+ val width = MeasureSpec.getSize(widthMeasureSpec)
51
+ val height = MeasureSpec.getSize(heightMeasureSpec)
52
+ for (i in 0 until childCount) {
53
+ val child = getChildAt(i)
54
+ child.measure(
55
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
56
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
57
+ )
58
+ }
59
+ setMeasuredDimension(width, height)
32
60
  }
33
- setMeasuredDimension(width, height)
34
- }
35
61
 
36
62
  }
@@ -44,7 +44,9 @@ class SpallaPlayerModule(reactContext: ReactApplicationContext) :
44
44
  if (uiManager is UIManager) {
45
45
  uiManager.resolveView(tag)?.let { view ->
46
46
  if (view is SpallaPlayerContainerView) {
47
- view.spallaPlayerView.play()
47
+ view.post {
48
+ view.spallaPlayerView.play()
49
+ }
48
50
  } else {
49
51
  throw ClassCastException(
50
52
  "Cannot play: view with tag #$tag is not a SpallaPlayerView"
@@ -78,7 +80,9 @@ class SpallaPlayerModule(reactContext: ReactApplicationContext) :
78
80
  if (uiManager is UIManager) {
79
81
  uiManager.resolveView(tag)?.let { view ->
80
82
  if (view is SpallaPlayerContainerView) {
81
- view.spallaPlayerView.pause()
83
+ view.post {
84
+ view.spallaPlayerView.pause()
85
+ }
82
86
  } else {
83
87
  throw ClassCastException(
84
88
  "Cannot pause: view with tag #$tag is not a SpallaPlayerView"
@@ -103,62 +107,114 @@ class SpallaPlayerModule(reactContext: ReactApplicationContext) :
103
107
  }
104
108
  }
105
109
  }
106
-
107
-
108
110
  }
109
111
 
110
112
  @ReactMethod
111
113
  fun seekTo(tag: Int, time: Double) {
112
- _reactContext.getNativeModule(UIManagerModule::class.java)!!
113
- .prependUIBlock { nativeViewHierarchyManager: NativeViewHierarchyManager ->
114
- val playerView = nativeViewHierarchyManager.resolveView(tag)
115
- if (playerView is SpallaPlayerContainerView) {
116
- playerView.spallaPlayerView.seekTo(time)
117
- } else {
118
- throw ClassCastException(
119
- String.format(
120
- "Cannot play: view with tag #%d is not a SpallaPplayerView",
121
- tag
114
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
115
+ val uiManager = UIManagerHelper.getUIManager(_reactContext, UIManagerType.FABRIC)
116
+ if (uiManager is UIManager) {
117
+ uiManager.resolveView(tag)?.let { view ->
118
+ if (view is SpallaPlayerContainerView) {
119
+ view.post {
120
+ view.spallaPlayerView.seekTo(time)
121
+ }
122
+ } else {
123
+ throw ClassCastException(
124
+ "Cannot play: view with tag #$tag is not a SpallaPlayerView"
122
125
  )
123
- )
126
+ }
124
127
  }
125
128
  }
129
+ } else {
130
+ _reactContext.getNativeModule(UIManagerModule::class.java)!!
131
+ .prependUIBlock { nativeViewHierarchyManager: NativeViewHierarchyManager ->
132
+ val playerView = nativeViewHierarchyManager.resolveView(tag)
133
+ if (playerView is SpallaPlayerContainerView) {
134
+ playerView.spallaPlayerView.seekTo(time)
135
+ } else {
136
+ throw ClassCastException(
137
+ String.format(
138
+ "Cannot play: view with tag #%d is not a SpallaPplayerView",
139
+ tag
140
+ )
141
+ )
142
+ }
143
+ }
144
+ }
126
145
  }
127
146
 
128
147
  @ReactMethod
129
148
  fun selectSubtitle(tag: Int, subtitle: String?) {
130
- _reactContext.getNativeModule(UIManagerModule::class.java)!!
131
- .prependUIBlock { nativeViewHierarchyManager: NativeViewHierarchyManager ->
132
- val playerView = nativeViewHierarchyManager.resolveView(tag)
133
- if (playerView is SpallaPlayerContainerView) {
134
- playerView.spallaPlayerView.selectSubtitle(subtitle)
135
- } else {
136
- throw ClassCastException(
137
- String.format(
138
- "Cannot play: view with tag #%d is not a SpallaPplayerView",
139
- tag
149
+
150
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
151
+ val uiManager = UIManagerHelper.getUIManager(_reactContext, UIManagerType.FABRIC)
152
+ if (uiManager is UIManager) {
153
+ uiManager.resolveView(tag)?.let { view ->
154
+ if (view is SpallaPlayerContainerView) {
155
+ view.post {
156
+ view.spallaPlayerView.selectSubtitle(subtitle)
157
+ }
158
+ } else {
159
+ throw ClassCastException(
160
+ "Cannot play: view with tag #$tag is not a SpallaPlayerView"
140
161
  )
141
- )
162
+ }
142
163
  }
143
164
  }
165
+ } else {
166
+
167
+ _reactContext.getNativeModule(UIManagerModule::class.java)!!
168
+ .prependUIBlock { nativeViewHierarchyManager: NativeViewHierarchyManager ->
169
+ val playerView = nativeViewHierarchyManager.resolveView(tag)
170
+ if (playerView is SpallaPlayerContainerView) {
171
+ playerView.spallaPlayerView.selectSubtitle(subtitle)
172
+ } else {
173
+ throw ClassCastException(
174
+ String.format(
175
+ "Cannot play: view with tag #%d is not a SpallaPplayerView",
176
+ tag
177
+ )
178
+ )
179
+ }
180
+ }
181
+ }
144
182
  }
145
183
 
146
184
  @ReactMethod
147
185
  fun selectPlaybackRate(tag: Int, rate: Double) {
148
- _reactContext.getNativeModule(UIManagerModule::class.java)!!
149
- .prependUIBlock { nativeViewHierarchyManager: NativeViewHierarchyManager ->
150
- val playerView = nativeViewHierarchyManager.resolveView(tag)
151
- if (playerView is SpallaPlayerContainerView) {
152
- playerView.spallaPlayerView.selectPlaybackRate(rate)
153
- } else {
154
- throw ClassCastException(
155
- String.format(
156
- "Cannot play: view with tag #%d is not a SpallaPplayerView",
157
- tag
186
+
187
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
188
+ val uiManager = UIManagerHelper.getUIManager(_reactContext, UIManagerType.FABRIC)
189
+ if (uiManager is UIManager) {
190
+ uiManager.resolveView(tag)?.let { view ->
191
+ if (view is SpallaPlayerContainerView) {
192
+ view.post {
193
+ view.spallaPlayerView.play()
194
+ }
195
+ } else {
196
+ throw ClassCastException(
197
+ "Cannot play: view with tag #$tag is not a SpallaPlayerView"
158
198
  )
159
- )
199
+ }
160
200
  }
161
201
  }
202
+ } else {
203
+ _reactContext.getNativeModule(UIManagerModule::class.java)!!
204
+ .prependUIBlock { nativeViewHierarchyManager: NativeViewHierarchyManager ->
205
+ val playerView = nativeViewHierarchyManager.resolveView(tag)
206
+ if (playerView is SpallaPlayerContainerView) {
207
+ playerView.spallaPlayerView.selectPlaybackRate(rate)
208
+ } else {
209
+ throw ClassCastException(
210
+ String.format(
211
+ "Cannot play: view with tag #%d is not a SpallaPplayerView",
212
+ tag
213
+ )
214
+ )
215
+ }
216
+ }
217
+ }
162
218
  }
163
219
 
164
220
  @ReactMethod
@@ -168,7 +224,9 @@ class SpallaPlayerModule(reactContext: ReactApplicationContext) :
168
224
  if (uiManager is UIManager) {
169
225
  uiManager.resolveView(tag)?.let { view ->
170
226
  if (view is SpallaPlayerContainerView) {
171
- view.spallaPlayerView.pause()
227
+ view.post {
228
+ view.spallaPlayerView.pause()
229
+ }
172
230
  }
173
231
  }
174
232
  }
@@ -189,5 +247,4 @@ class SpallaPlayerModule(reactContext: ReactApplicationContext) :
189
247
  SpallaSDK.initialize(_reactContext, token)
190
248
  }
191
249
 
192
-
193
250
  }
@@ -18,216 +18,232 @@ import java.util.Timer
18
18
  import java.util.TimerTask
19
19
 
20
20
  class RNSpallaPlayerManager() : ViewGroupManager<SpallaPlayerContainerView>(),
21
- SpallaPlayerListener, SpallaPlayerFullScreenListener {
22
- private var _playerView: SpallaPlayerView? = null
23
- private var _reactContext: ReactContext? = null
24
- private var _container: SpallaPlayerContainerView? = null
25
-
26
- private var contentId: String? = null
27
- private var startTime: Double? = null
28
- private var subtitle: String? = null
29
- private var loadTimer: Timer? = null
30
- private var playbackRate: Double = 1.0
31
- private var hideUI: Boolean? = null
32
-
33
- override fun getName() = "RNSpallaPlayer"
34
-
35
- override fun createViewInstance(context: ThemedReactContext): SpallaPlayerContainerView {
36
- _reactContext = context
37
- val container = SpallaPlayerContainerView(context)
38
- _playerView = container.spallaPlayerView
39
- _playerView?.registerPlayerListener(this)
40
- _playerView?.registerFullScreenListener(this)
41
- this._container = container
42
-
43
- return container
44
- }
45
-
46
- override fun getExportedCustomBubblingEventTypeConstants(): MutableMap<String, Any> {
47
- val eventMap = mutableMapOf<String, Any>()
48
-
49
- eventMap["onPlayerEvent"] = mapOf(
50
- "phasedRegistrationNames" to mapOf(
51
- "bubbled" to "onPlayerEvent"
52
- )
53
- )
54
-
55
- return eventMap
56
- }
57
-
58
- override fun onDropViewInstance(view: SpallaPlayerContainerView) {
59
- Log.v("RNSpallaPlayerManager", "onDropViewInstance")
60
-
61
- try {
62
- view.spallaPlayerView.onDestroy()
63
- } catch (e: Exception) {
64
- e.printStackTrace()
65
- }
66
- super.onDropViewInstance(view)
67
- }
68
-
69
- override fun addView(parent: SpallaPlayerContainerView, child: View, index: Int) {
70
- parent.addView(child, index)
71
- }
72
-
73
- override fun removeViewAt(parent: SpallaPlayerContainerView, index: Int) {
74
- parent.removeViewAt(index)
75
- }
76
-
77
- override fun getChildCount(parent: SpallaPlayerContainerView): Int {
78
- return parent.childCount
79
- }
80
-
81
- override fun getChildAt(parent: SpallaPlayerContainerView, index: Int): View {
82
- return parent.getChildAt(index)
83
- }
84
-
85
- @ReactProp(name = "contentId")
86
- fun setContentId(view: SpallaPlayerContainerView, contentId: String) {
87
- this.contentId = contentId
88
- checkAndLoadPlayer(view)
89
- }
90
-
91
- @ReactProp(name = "muted")
92
- fun setMuted(view: SpallaPlayerContainerView, muted: Boolean) {
93
- _playerView?.setMuted(muted)
94
- }
95
-
96
- @ReactProp(name = "startTime")
97
- fun setStartTime(view: SpallaPlayerContainerView, startTime: Double) {
98
- this.startTime = startTime
99
- //checkAndLoadPlayer(view)
100
- }
101
-
102
- @ReactProp(name = "subtitle")
103
- fun setSubtitle(view: SpallaPlayerContainerView, subtitle: String?) {
104
- this.subtitle = subtitle
105
- _playerView?.selectSubtitle(subtitle)
106
- }
107
-
108
- @ReactProp(name = "playbackRate")
109
- fun setPlaybackRate(view: SpallaPlayerContainerView, playbackRate: Double) {
110
- if (playbackRate > 0) {
111
- this.playbackRate = playbackRate
112
- _playerView?.selectPlaybackRate(playbackRate)
113
- }
114
- }
115
-
116
- @ReactProp(name = "hideUI")
117
- fun setPlaybackRate(view: SpallaPlayerContainerView, hideUI: Boolean) {
118
- this.hideUI = hideUI
119
- checkAndLoadPlayer(view)
120
- }
121
-
122
- private fun checkAndLoadPlayer(view: SpallaPlayerContainerView) {
123
- if (contentId != null && startTime != null && hideUI != null) {
124
- view.spallaPlayerView.load(contentId!!, true, startTime!!, subtitle, hideUI!!)
125
- }
126
- }
127
-
128
- private fun startLoadTimer(view: SpallaPlayerView) {
129
- // Cancel any existing timer
130
- loadTimer?.cancel()
131
-
132
- // Start a new timer to check if all required properties are set
133
- loadTimer = Timer()
134
- loadTimer?.schedule(object : TimerTask() {
135
- override fun run() {
21
+ SpallaPlayerListener, SpallaPlayerFullScreenListener {
22
+ private var _playerView: SpallaPlayerView? = null
23
+ private var _reactContext: ReactContext? = null
24
+ private var _container: SpallaPlayerContainerView? = null
25
+
26
+ private var contentId: String? = null
27
+ private var startTime: Double? = null
28
+ private var subtitle: String? = null
29
+ private var loadTimer: Timer? = null
30
+ private var playbackRate: Double = 1.0
31
+ private var hideUI: Boolean? = null
32
+
33
+ override fun getName() = "RNSpallaPlayer"
34
+
35
+ override fun createViewInstance(context: ThemedReactContext): SpallaPlayerContainerView {
36
+ _reactContext = context
37
+ val container = SpallaPlayerContainerView(context)
38
+ _playerView = container.spallaPlayerView
39
+ _playerView?.registerPlayerListener(this)
40
+ _playerView?.registerFullScreenListener(this)
41
+ this._container = container
42
+
43
+ return container
44
+ }
45
+
46
+ override fun getExportedCustomBubblingEventTypeConstants(): MutableMap<String, Any> {
47
+ val eventMap = mutableMapOf<String, Any>()
48
+
49
+ eventMap["onPlayerEvent"] = mapOf(
50
+ "phasedRegistrationNames" to mapOf(
51
+ "bubbled" to "onPlayerEvent"
52
+ )
53
+ )
54
+
55
+ return eventMap
56
+ }
57
+
58
+ override fun onDropViewInstance(view: SpallaPlayerContainerView) {
59
+ Log.v("RNSpallaPlayerManager", "onDropViewInstance")
60
+ view.post {
61
+ try {
62
+ loadTimer?.cancel()
63
+ view.spallaPlayerView.onDestroy()
64
+ } catch (e: Exception) {
65
+ e.printStackTrace()
66
+ }
67
+ }
68
+ super.onDropViewInstance(view)
69
+ }
70
+
71
+ override fun addView(parent: SpallaPlayerContainerView, child: View, index: Int) {
72
+ parent.addView(child, index)
73
+ }
74
+
75
+ override fun removeViewAt(parent: SpallaPlayerContainerView, index: Int) {
76
+ parent.removeViewAt(index)
77
+ }
78
+
79
+ override fun getChildCount(parent: SpallaPlayerContainerView): Int {
80
+ return parent.childCount
81
+ }
82
+
83
+ override fun getChildAt(parent: SpallaPlayerContainerView, index: Int): View {
84
+ return parent.getChildAt(index)
85
+ }
86
+
87
+ @ReactProp(name = "contentId")
88
+ fun setContentId(view: SpallaPlayerContainerView, contentId: String) {
89
+ this.contentId = contentId
90
+ //delay initialization for a bit
136
91
  loadTimer?.cancel()
137
- loadTimer = null
138
- // Call view.load with the required properties
139
- view.load(contentId!!, true, startTime!!, subtitle = subtitle, hideUI!!)
140
- }
141
- }, 300) // Delay of 200ms to allow all properties to be set
142
- }
143
-
144
- override fun onEvent(event: SpallaPlayerEvent) {
145
- val map: WritableMap = Arguments.createMap()
146
-
147
- Log.v("RNSpallaPlayerManager", "onEvent: $event")
148
- when (event) {
149
- is DurationUpdate -> {
150
- map.putString("event", "durationUpdate")
151
- map.putDouble("duration", event.duration)
152
- }
153
-
154
- Ended -> map.putString("event", "ended")
155
- is Error -> {
156
- map.putString("event", "error")
157
- map.putString("message", event.message)
158
- }
159
-
160
- Pause -> map.putString("event", "pause")
161
- Play -> map.putString("event", "play")
162
- Playing -> map.putString("event", "playing")
163
- is TimeUpdate -> {
164
- map.putString("event", "timeUpdate")
165
- map.putDouble("time", event.currentTime)
166
- }
167
-
168
- Waiting -> map.putString("event", "buffering")
169
- is SubtitlesAvailable -> {
170
- map.putString("event", "subtitlesAvailable")
171
-
172
- var subs = Arguments.createArray()
173
- event.subtitles.forEach {
174
- subs.pushString(it)
92
+ loadTimer = Timer()
93
+ loadTimer?.schedule(object : TimerTask() {
94
+ override fun run() {
95
+ checkAndLoadPlayer(view)
96
+ }
97
+ }, 100)
98
+ }
99
+
100
+ @ReactProp(name = "muted")
101
+ fun setMuted(view: SpallaPlayerContainerView, muted: Boolean) {
102
+ _playerView?.setMuted(muted)
103
+ }
104
+
105
+ @ReactProp(name = "startTime")
106
+ fun setStartTime(view: SpallaPlayerContainerView, startTime: Double) {
107
+ this.startTime = startTime
108
+ //checkAndLoadPlayer(view)
109
+ }
110
+
111
+ @ReactProp(name = "subtitle")
112
+ fun setSubtitle(view: SpallaPlayerContainerView, subtitle: String?) {
113
+ this.subtitle = subtitle
114
+ _playerView?.selectSubtitle(subtitle)
115
+ }
116
+
117
+ @ReactProp(name = "playbackRate")
118
+ fun setPlaybackRate(view: SpallaPlayerContainerView, playbackRate: Double) {
119
+ if (playbackRate > 0) {
120
+ this.playbackRate = playbackRate
121
+ _playerView?.selectPlaybackRate(playbackRate)
122
+ }
123
+ }
124
+
125
+ @ReactProp(name = "hideUI")
126
+ fun setHideUI(view: SpallaPlayerContainerView, hideUI: Boolean) {
127
+ this.hideUI = hideUI
128
+ }
129
+
130
+ private fun checkAndLoadPlayer(view: SpallaPlayerContainerView) {
131
+ if (contentId != null && startTime != null && hideUI != null) {
132
+ view.post {
133
+ view.spallaPlayerView.load(contentId!!, true, startTime!!, subtitle, hideUI!!)
134
+ }
175
135
  }
176
- map.putArray("subtitles", subs)
177
- }
178
-
179
- is SubtitleSelected -> {
180
- map.putString("event", "subtitleSelected")
181
- map.putString("subtitle", event.subtitle)
182
- }
183
-
184
- is MetadataLoaded -> {
185
- map.putString("event", "metadataLoaded")
186
- map.putBoolean("isLive", event.metadata.isLive)
187
- map.putDouble("duration", event.metadata.duration)
188
-
189
- // make sure current playback rate is applied if set initially
190
- _playerView?.selectPlaybackRate(playbackRate)
191
- }
192
-
193
- is PlaybackRateSelected -> {
194
- map.putString("event", "playbackRateSelected")
195
- map.putDouble("rate", event.rate)
196
- }
197
-
198
- }
199
- _container?.let { container ->
200
- _reactContext?.getJSModule(RCTEventEmitter::class.java)?.receiveEvent(
201
- container.id,
202
- "onPlayerEvent",
203
- map
204
- )
205
- }
206
- }
207
-
208
- override fun onEnterFullScreen() {
209
- Log.v("SpallaPlayerViewManager", "onEnterFullScreen")
210
- val map: WritableMap = Arguments.createMap()
211
- map.putString("event", "enterFullScreen")
212
- _container?.let { container ->
213
- _reactContext?.getJSModule(RCTEventEmitter::class.java)?.receiveEvent(
214
- container.id,
215
- "onPlayerEvent",
216
- map
217
- )
218
- }
219
- }
220
-
221
- override fun onExitFullScreen() {
222
- val map: WritableMap = Arguments.createMap()
223
- map.putString("event", "exitFullScreen")
224
- _container?.let { container ->
225
- _reactContext?.getJSModule(RCTEventEmitter::class.java)?.receiveEvent(
226
- container.id,
227
- "onPlayerEvent",
228
- map
229
- )
230
- }
231
- }
136
+ }
137
+
138
+ override fun onEvent(event: SpallaPlayerEvent) {
139
+ val map: WritableMap = Arguments.createMap()
140
+
141
+ Log.v("RNSpallaPlayerManager", "onEvent: $event")
142
+ when (event) {
143
+ is DurationUpdate -> {
144
+ map.putString("event", "durationUpdate")
145
+ map.putDouble("duration", event.duration)
146
+ requestLayout()
147
+ }
148
+
149
+ Ended -> map.putString("event", "ended")
150
+ is Error -> {
151
+ map.putString("event", "error")
152
+ map.putString("message", event.message)
153
+ }
154
+
155
+ Pause -> map.putString("event", "pause")
156
+ Play -> map.putString("event", "play")
157
+ Playing -> map.putString("event", "playing")
158
+ is TimeUpdate -> {
159
+ map.putString("event", "timeUpdate")
160
+ map.putDouble("time", event.currentTime)
161
+ }
162
+
163
+ Waiting -> map.putString("event", "buffering")
164
+ is SubtitlesAvailable -> {
165
+ map.putString("event", "subtitlesAvailable")
166
+
167
+ var subs = Arguments.createArray()
168
+ event.subtitles.forEach {
169
+ subs.pushString(it)
170
+ }
171
+ map.putArray("subtitles", subs)
172
+ }
173
+
174
+ is SubtitleSelected -> {
175
+ map.putString("event", "subtitleSelected")
176
+ map.putString("subtitle", event.subtitle)
177
+ }
178
+
179
+ is MetadataLoaded -> {
180
+ map.putString("event", "metadataLoaded")
181
+ map.putBoolean("isLive", event.metadata.isLive)
182
+ map.putDouble("duration", event.metadata.duration)
183
+
184
+ // make sure current playback rate is applied if set initially
185
+ _playerView?.selectPlaybackRate(playbackRate)
186
+ requestLayout()
187
+ }
188
+
189
+ is PlaybackRateSelected -> {
190
+ map.putString("event", "playbackRateSelected")
191
+ map.putDouble("rate", event.rate)
192
+ requestLayout()
193
+ }
194
+
195
+ }
196
+ _container?.let { container ->
197
+ _reactContext?.getJSModule(RCTEventEmitter::class.java)?.receiveEvent(
198
+ container.id,
199
+ "onPlayerEvent",
200
+ map
201
+ )
202
+ }
203
+ }
204
+
205
+ override fun onEnterFullScreen() {
206
+ Log.v("SpallaPlayerViewManager", "onEnterFullScreen")
207
+ val map: WritableMap = Arguments.createMap()
208
+ map.putString("event", "enterFullScreen")
209
+ _container?.let { container ->
210
+ _reactContext?.getJSModule(RCTEventEmitter::class.java)?.receiveEvent(
211
+ container.id,
212
+ "onPlayerEvent",
213
+ map
214
+ )
215
+ }
216
+ }
217
+
218
+ override fun onExitFullScreen() {
219
+ val map: WritableMap = Arguments.createMap()
220
+ map.putString("event", "exitFullScreen")
221
+ _container?.let { container ->
222
+ _reactContext?.getJSModule(RCTEventEmitter::class.java)?.receiveEvent(
223
+ container.id,
224
+ "onPlayerEvent",
225
+ map
226
+ )
227
+ }
228
+ }
229
+
230
+ fun requestLayout() {
231
+ _playerView?.post(measureAndLayout)
232
+ }
233
+
234
+ private val measureAndLayout = Runnable {
235
+ _playerView?.let {
236
+ it.measure(
237
+ View.MeasureSpec.makeMeasureSpec(it.width, View.MeasureSpec.EXACTLY),
238
+ View.MeasureSpec.makeMeasureSpec(it.height, View.MeasureSpec.EXACTLY)
239
+ )
240
+ it.layout(
241
+ it.left,
242
+ it.top,
243
+ it.right,
244
+ it.bottom
245
+ )
246
+ }
247
+ }
232
248
 
233
249
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-spalla-player",
3
- "version": "0.13.4",
3
+ "version": "0.14.1",
4
4
  "description": "Spalla SDK for RN",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/commonjs/index.js",