expo-video 2.0.0 → 2.0.2
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/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,17 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 2.0.2 — 2024-11-29
|
|
14
|
+
|
|
15
|
+
_This version does not introduce any user-facing changes._
|
|
16
|
+
|
|
17
|
+
## 2.0.1 — 2024-11-19
|
|
18
|
+
|
|
19
|
+
### 🐛 Bug fixes
|
|
20
|
+
|
|
21
|
+
- [Android] Fixed `border` related props weren't applied correctly. ([#33075](https://github.com/expo/expo/pull/33075) by [@lukmccall](https://github.com/lukmccall))
|
|
22
|
+
- [Android] Fix controls sometimes flashing on initial display of the view, when `useNativeControls` is `false` ([#33238](https://github.com/expo/expo/pull/33238) by [@behenate](https://github.com/behenate))
|
|
23
|
+
|
|
13
24
|
## 2.0.0 — 2024-11-11
|
|
14
25
|
|
|
15
26
|
### 💡 Others
|
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
3
|
group = 'host.exp.exponent'
|
|
4
|
-
version = '2.0.
|
|
4
|
+
version = '2.0.2'
|
|
5
5
|
|
|
6
6
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
7
|
apply from: expoModulesCorePlugin
|
|
@@ -14,7 +14,7 @@ android {
|
|
|
14
14
|
namespace "expo.modules.video"
|
|
15
15
|
defaultConfig {
|
|
16
16
|
versionCode 1
|
|
17
|
-
versionName '2.0.
|
|
17
|
+
versionName '2.0.2'
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -7,10 +7,6 @@ import androidx.media3.common.PlaybackParameters
|
|
|
7
7
|
import androidx.media3.common.Player.REPEAT_MODE_OFF
|
|
8
8
|
import androidx.media3.common.Player.REPEAT_MODE_ONE
|
|
9
9
|
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
10
|
-
import com.facebook.react.uimanager.PixelUtil
|
|
11
|
-
import com.facebook.react.uimanager.Spacing
|
|
12
|
-
import com.facebook.react.uimanager.ViewProps
|
|
13
|
-
import com.facebook.yoga.YogaConstants
|
|
14
10
|
import expo.modules.kotlin.apifeatures.EitherType
|
|
15
11
|
import expo.modules.kotlin.functions.Coroutine
|
|
16
12
|
import expo.modules.kotlin.modules.Module
|
|
@@ -22,8 +18,6 @@ import expo.modules.video.player.VideoPlayer
|
|
|
22
18
|
import expo.modules.video.records.BufferOptions
|
|
23
19
|
import expo.modules.video.records.SubtitleTrack
|
|
24
20
|
import expo.modules.video.records.VideoSource
|
|
25
|
-
import expo.modules.video.utils.ifYogaDefinedUse
|
|
26
|
-
import expo.modules.video.utils.makeYogaUndefinedIfNegative
|
|
27
21
|
import expo.modules.video.utils.runWithPiPMisconfigurationSoftHandling
|
|
28
22
|
import kotlinx.coroutines.async
|
|
29
23
|
import kotlinx.coroutines.awaitAll
|
|
@@ -80,55 +74,6 @@ class VideoModule : Module() {
|
|
|
80
74
|
view.videoPlayer?.requiresLinearPlayback = linearPlayback
|
|
81
75
|
}
|
|
82
76
|
|
|
83
|
-
PropGroup(
|
|
84
|
-
ViewProps.BORDER_RADIUS to 0,
|
|
85
|
-
ViewProps.BORDER_TOP_LEFT_RADIUS to 1,
|
|
86
|
-
ViewProps.BORDER_TOP_RIGHT_RADIUS to 2,
|
|
87
|
-
ViewProps.BORDER_BOTTOM_RIGHT_RADIUS to 3,
|
|
88
|
-
ViewProps.BORDER_BOTTOM_LEFT_RADIUS to 4,
|
|
89
|
-
ViewProps.BORDER_TOP_START_RADIUS to 5,
|
|
90
|
-
ViewProps.BORDER_TOP_END_RADIUS to 6,
|
|
91
|
-
ViewProps.BORDER_BOTTOM_START_RADIUS to 7,
|
|
92
|
-
ViewProps.BORDER_BOTTOM_END_RADIUS to 8
|
|
93
|
-
) { view: VideoView, index: Int, borderRadius: Float? ->
|
|
94
|
-
val radius = makeYogaUndefinedIfNegative(borderRadius ?: YogaConstants.UNDEFINED)
|
|
95
|
-
view.setBorderRadius(index, radius)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
PropGroup(
|
|
99
|
-
ViewProps.BORDER_WIDTH to Spacing.ALL,
|
|
100
|
-
ViewProps.BORDER_LEFT_WIDTH to Spacing.LEFT,
|
|
101
|
-
ViewProps.BORDER_RIGHT_WIDTH to Spacing.RIGHT,
|
|
102
|
-
ViewProps.BORDER_TOP_WIDTH to Spacing.TOP,
|
|
103
|
-
ViewProps.BORDER_BOTTOM_WIDTH to Spacing.BOTTOM,
|
|
104
|
-
ViewProps.BORDER_START_WIDTH to Spacing.START,
|
|
105
|
-
ViewProps.BORDER_END_WIDTH to Spacing.END
|
|
106
|
-
) { view: VideoView, index: Int, width: Float? ->
|
|
107
|
-
val pixelWidth = makeYogaUndefinedIfNegative(width ?: YogaConstants.UNDEFINED)
|
|
108
|
-
.ifYogaDefinedUse(PixelUtil::toPixelFromDIP)
|
|
109
|
-
view.setBorderWidth(index, pixelWidth)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
PropGroup(
|
|
113
|
-
ViewProps.BORDER_COLOR to Spacing.ALL,
|
|
114
|
-
ViewProps.BORDER_LEFT_COLOR to Spacing.LEFT,
|
|
115
|
-
ViewProps.BORDER_RIGHT_COLOR to Spacing.RIGHT,
|
|
116
|
-
ViewProps.BORDER_TOP_COLOR to Spacing.TOP,
|
|
117
|
-
ViewProps.BORDER_BOTTOM_COLOR to Spacing.BOTTOM,
|
|
118
|
-
ViewProps.BORDER_START_COLOR to Spacing.START,
|
|
119
|
-
ViewProps.BORDER_END_COLOR to Spacing.END
|
|
120
|
-
) { view: VideoView, index: Int, color: Int ->
|
|
121
|
-
view.setBorderColor(index, color)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
Prop("borderStyle") { view: VideoView, borderStyle: String? ->
|
|
125
|
-
view.setBorderStyle(borderStyle)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
OnViewDidUpdateProps { view: VideoView ->
|
|
129
|
-
view.didUpdateProps()
|
|
130
|
-
}
|
|
131
|
-
|
|
132
77
|
AsyncFunction("enterFullscreen") { view: VideoView ->
|
|
133
78
|
view.enterFullscreen()
|
|
134
79
|
}
|
|
@@ -150,6 +95,12 @@ class VideoModule : Module() {
|
|
|
150
95
|
OnViewDestroys {
|
|
151
96
|
VideoManager.unregisterVideoView(it)
|
|
152
97
|
}
|
|
98
|
+
|
|
99
|
+
OnViewDidUpdateProps { view ->
|
|
100
|
+
if (view.playerView.useController != view.useNativeControls) {
|
|
101
|
+
view.playerView.useController = view.useNativeControls
|
|
102
|
+
}
|
|
103
|
+
}
|
|
153
104
|
}
|
|
154
105
|
|
|
155
106
|
Class(VideoPlayer::class) {
|
|
@@ -4,7 +4,6 @@ import android.app.Activity
|
|
|
4
4
|
import android.app.PictureInPictureParams
|
|
5
5
|
import android.content.Context
|
|
6
6
|
import android.content.Intent
|
|
7
|
-
import android.graphics.Canvas
|
|
8
7
|
import android.os.Build
|
|
9
8
|
import android.util.Rational
|
|
10
9
|
import android.view.View
|
|
@@ -14,27 +13,16 @@ import android.widget.ImageButton
|
|
|
14
13
|
import androidx.fragment.app.FragmentActivity
|
|
15
14
|
import androidx.media3.common.Tracks
|
|
16
15
|
import androidx.media3.ui.PlayerView
|
|
17
|
-
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
18
|
-
import com.facebook.react.modules.i18nmanager.I18nUtil
|
|
19
|
-
import com.facebook.react.uimanager.LengthPercentage
|
|
20
|
-
import com.facebook.react.uimanager.LengthPercentageType
|
|
21
|
-
import com.facebook.react.uimanager.PixelUtil
|
|
22
|
-
import com.facebook.react.uimanager.Spacing
|
|
23
|
-
import com.facebook.react.uimanager.drawable.CSSBackgroundDrawable
|
|
24
|
-
import com.facebook.react.uimanager.style.BorderRadiusProp
|
|
25
|
-
import com.facebook.yoga.YogaConstants
|
|
26
16
|
import expo.modules.kotlin.AppContext
|
|
27
17
|
import expo.modules.kotlin.viewevent.EventDispatcher
|
|
28
18
|
import expo.modules.kotlin.views.ExpoView
|
|
29
19
|
import expo.modules.video.delegates.IgnoreSameSet
|
|
30
|
-
import expo.modules.video.drawing.OutlineProvider
|
|
31
20
|
import expo.modules.video.enums.ContentFit
|
|
32
21
|
import expo.modules.video.player.VideoPlayer
|
|
33
22
|
import expo.modules.video.player.VideoPlayerListener
|
|
34
23
|
import expo.modules.video.utils.applyAutoEnterPiP
|
|
35
24
|
import expo.modules.video.utils.applyRectHint
|
|
36
25
|
import expo.modules.video.utils.calculateRectHint
|
|
37
|
-
import expo.modules.video.utils.ifYogaDefinedUse
|
|
38
26
|
import java.util.UUID
|
|
39
27
|
|
|
40
28
|
// https://developer.android.com/guide/topics/media/media3/getting-started/migration-guide#improvements_in_media3
|
|
@@ -64,32 +52,6 @@ class VideoView(context: Context, appContext: AppContext) : ExpoView(context, ap
|
|
|
64
52
|
private val rootViewChildrenOriginalVisibility: ArrayList<Int> = arrayListOf()
|
|
65
53
|
private var pictureInPictureHelperTag: String? = null
|
|
66
54
|
|
|
67
|
-
private var shouldInvalided = false
|
|
68
|
-
|
|
69
|
-
private val outlineProvider = OutlineProvider(context)
|
|
70
|
-
|
|
71
|
-
@UnstableReactNativeAPI
|
|
72
|
-
private val borderDrawableLazyHolder = lazy {
|
|
73
|
-
CSSBackgroundDrawable(context).apply {
|
|
74
|
-
callback = this@VideoView
|
|
75
|
-
|
|
76
|
-
outlineProvider.borderRadiiConfig
|
|
77
|
-
.map { it.ifYogaDefinedUse(PixelUtil::toPixelFromDIP) }
|
|
78
|
-
.withIndex()
|
|
79
|
-
.forEach { (i, radius) ->
|
|
80
|
-
if (i == 0) {
|
|
81
|
-
setBorderRadius(BorderRadiusProp.BORDER_RADIUS, LengthPercentage(radius, LengthPercentageType.POINT))
|
|
82
|
-
} else {
|
|
83
|
-
setBorderRadius(BorderRadiusProp.entries[i - 1], LengthPercentage(radius, LengthPercentageType.POINT))
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
@UnstableReactNativeAPI
|
|
90
|
-
private val borderDrawable
|
|
91
|
-
get() = borderDrawableLazyHolder.value
|
|
92
|
-
|
|
93
55
|
var autoEnterPiP: Boolean by IgnoreSameSet(false) { new, _ ->
|
|
94
56
|
applyAutoEnterPiP(currentActivity, new)
|
|
95
57
|
}
|
|
@@ -145,6 +107,9 @@ class VideoView(context: Context, appContext: AppContext) : ExpoView(context, ap
|
|
|
145
107
|
init {
|
|
146
108
|
VideoManager.registerVideoView(this)
|
|
147
109
|
playerView.setFullscreenButtonClickListener { enterFullscreen() }
|
|
110
|
+
// The prop `useNativeControls` prop is sometimes applied after the view is created, and sometimes there is a visible
|
|
111
|
+
// flash of controls event when they are set to off. Initially we set it to `false` and apply it in `onAttachedToWindow` to avoid this.
|
|
112
|
+
this.playerView.useController = false
|
|
148
113
|
addView(
|
|
149
114
|
playerView,
|
|
150
115
|
ViewGroup.LayoutParams(
|
|
@@ -277,31 +242,6 @@ class VideoView(context: Context, appContext: AppContext) : ExpoView(context, ap
|
|
|
277
242
|
applyRectHint(currentActivity, calculateRectHint(playerView))
|
|
278
243
|
}
|
|
279
244
|
|
|
280
|
-
@UnstableReactNativeAPI
|
|
281
|
-
override fun draw(canvas: Canvas) {
|
|
282
|
-
// When the border-radii are not all the same, a convex-path
|
|
283
|
-
// is used for the Outline. Unfortunately clipping is not supported
|
|
284
|
-
// for convex-paths and we fallback to Canvas clipping.
|
|
285
|
-
outlineProvider.clipCanvasIfNeeded(canvas, this)
|
|
286
|
-
|
|
287
|
-
super.draw(canvas)
|
|
288
|
-
|
|
289
|
-
// Draw borders on top of the video
|
|
290
|
-
if (borderDrawableLazyHolder.isInitialized()) {
|
|
291
|
-
val newLayoutDirection = if (I18nUtil.instance.isRTL(context)) {
|
|
292
|
-
LAYOUT_DIRECTION_RTL
|
|
293
|
-
} else {
|
|
294
|
-
LAYOUT_DIRECTION_LTR
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
borderDrawable.apply {
|
|
298
|
-
layoutDirection = newLayoutDirection
|
|
299
|
-
setBounds(0, 0, width, height)
|
|
300
|
-
draw(canvas)
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
245
|
override fun onAttachedToWindow() {
|
|
306
246
|
super.onAttachedToWindow()
|
|
307
247
|
(currentActivity as? FragmentActivity)?.let {
|
|
@@ -326,78 +266,6 @@ class VideoView(context: Context, appContext: AppContext) : ExpoView(context, ap
|
|
|
326
266
|
applyAutoEnterPiP(currentActivity, false)
|
|
327
267
|
}
|
|
328
268
|
|
|
329
|
-
@UnstableReactNativeAPI
|
|
330
|
-
internal fun setBorderRadius(position: Int, borderRadius: Float) {
|
|
331
|
-
val isInvalidated = outlineProvider.setBorderRadius(borderRadius, position)
|
|
332
|
-
if (isInvalidated) {
|
|
333
|
-
invalidateOutline()
|
|
334
|
-
if (!outlineProvider.hasEqualCorners()) {
|
|
335
|
-
shouldInvalided = true
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// Setting the border-radius doesn't necessarily mean that a border
|
|
340
|
-
// should to be drawn. Only update the border-drawable when needed.
|
|
341
|
-
if (borderDrawableLazyHolder.isInitialized()) {
|
|
342
|
-
shouldInvalided = true
|
|
343
|
-
val radius = borderRadius.ifYogaDefinedUse(PixelUtil::toPixelFromDIP)
|
|
344
|
-
borderDrawableLazyHolder.value.apply {
|
|
345
|
-
if (position == 0) {
|
|
346
|
-
setBorderRadius(BorderRadiusProp.BORDER_RADIUS, LengthPercentage(radius, LengthPercentageType.POINT))
|
|
347
|
-
} else {
|
|
348
|
-
setBorderRadius(BorderRadiusProp.entries[position - 1], LengthPercentage(radius, LengthPercentageType.POINT))
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
@UnstableReactNativeAPI
|
|
355
|
-
internal fun setBorderWidth(position: Int, width: Float) {
|
|
356
|
-
borderDrawable.setBorderWidth(position, width)
|
|
357
|
-
shouldInvalided = true
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
@UnstableReactNativeAPI
|
|
361
|
-
internal fun setBorderColor(position: Int, rgb: Int) {
|
|
362
|
-
borderDrawable.setBorderColor(position, rgb)
|
|
363
|
-
shouldInvalided = true
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
@UnstableReactNativeAPI
|
|
367
|
-
internal fun setBorderStyle(style: String?) {
|
|
368
|
-
borderDrawable.setBorderStyle(style)
|
|
369
|
-
shouldInvalided = true
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
@UnstableReactNativeAPI
|
|
373
|
-
fun didUpdateProps() {
|
|
374
|
-
val hasBorder = if (borderDrawableLazyHolder.isInitialized()) {
|
|
375
|
-
val spacings = listOf(
|
|
376
|
-
Spacing.ALL,
|
|
377
|
-
Spacing.LEFT,
|
|
378
|
-
Spacing.RIGHT,
|
|
379
|
-
Spacing.TOP,
|
|
380
|
-
Spacing.BOTTOM,
|
|
381
|
-
Spacing.START,
|
|
382
|
-
Spacing.END
|
|
383
|
-
)
|
|
384
|
-
spacings
|
|
385
|
-
.any {
|
|
386
|
-
val boarderWidth = borderDrawable.getBorderWidthOrDefaultTo(YogaConstants.UNDEFINED, it)
|
|
387
|
-
boarderWidth != YogaConstants.UNDEFINED && boarderWidth > 0f
|
|
388
|
-
}
|
|
389
|
-
} else {
|
|
390
|
-
false
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// We need to enable drawing on the view to draw the border or background
|
|
394
|
-
setWillNotDraw(!isOpaque && !hasBorder)
|
|
395
|
-
if (shouldInvalided) {
|
|
396
|
-
shouldInvalided = false
|
|
397
|
-
invalidate()
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
269
|
companion object {
|
|
402
270
|
fun isPictureInPictureSupported(currentActivity: Activity): Boolean {
|
|
403
271
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && currentActivity.packageManager.hasSystemFeature(
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-video",
|
|
3
3
|
"title": "Expo Video",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.2",
|
|
5
5
|
"description": "A cross-platform, performant video component for React Native and Expo with Web support",
|
|
6
6
|
"main": "build/index.js",
|
|
7
7
|
"types": "build/index.d.ts",
|
|
@@ -38,5 +38,5 @@
|
|
|
38
38
|
"react": "*",
|
|
39
39
|
"react-native": "*"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "728158f99d680cf64fb06f08301d3806c18c6f63"
|
|
42
42
|
}
|