@granite-js/video 1.0.0

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/GraniteVideo.podspec +72 -0
  3. package/android/README.md +232 -0
  4. package/android/build.gradle +117 -0
  5. package/android/gradle.properties +8 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/java/run/granite/video/GraniteVideoModule.kt +70 -0
  8. package/android/src/main/java/run/granite/video/GraniteVideoPackage.kt +43 -0
  9. package/android/src/main/java/run/granite/video/GraniteVideoView.kt +384 -0
  10. package/android/src/main/java/run/granite/video/GraniteVideoViewManager.kt +318 -0
  11. package/android/src/main/java/run/granite/video/event/GraniteVideoEvents.kt +273 -0
  12. package/android/src/main/java/run/granite/video/event/VideoEventDispatcher.kt +66 -0
  13. package/android/src/main/java/run/granite/video/event/VideoEventListenerAdapter.kt +157 -0
  14. package/android/src/main/java/run/granite/video/provider/GraniteVideoProvider.kt +346 -0
  15. package/android/src/media3/AndroidManifest.xml +9 -0
  16. package/android/src/media3/java/run/granite/video/provider/media3/ExoPlayerProvider.kt +386 -0
  17. package/android/src/media3/java/run/granite/video/provider/media3/Media3ContentProvider.kt +29 -0
  18. package/android/src/media3/java/run/granite/video/provider/media3/Media3Initializer.kt +25 -0
  19. package/android/src/media3/java/run/granite/video/provider/media3/factory/ExoPlayerFactory.kt +32 -0
  20. package/android/src/media3/java/run/granite/video/provider/media3/factory/MediaSourceFactory.kt +61 -0
  21. package/android/src/media3/java/run/granite/video/provider/media3/factory/TrackSelectorFactory.kt +26 -0
  22. package/android/src/media3/java/run/granite/video/provider/media3/factory/VideoSurfaceFactory.kt +62 -0
  23. package/android/src/media3/java/run/granite/video/provider/media3/listener/ExoPlayerEventListener.kt +104 -0
  24. package/android/src/media3/java/run/granite/video/provider/media3/scheduler/ProgressScheduler.kt +56 -0
  25. package/android/src/test/java/run/granite/video/GraniteVideoViewRobolectricTest.kt +598 -0
  26. package/android/src/test/java/run/granite/video/event/VideoEventListenerAdapterTest.kt +319 -0
  27. package/android/src/test/java/run/granite/video/helpers/FakeGraniteVideoProvider.kt +161 -0
  28. package/android/src/test/java/run/granite/video/helpers/TestProgressScheduler.kt +42 -0
  29. package/android/src/test/java/run/granite/video/provider/GraniteVideoRegistryTest.kt +232 -0
  30. package/android/src/test/java/run/granite/video/provider/ProviderContractTest.kt +174 -0
  31. package/android/src/test/java/run/granite/video/provider/media3/listener/ExoPlayerEventListenerTest.kt +243 -0
  32. package/android/src/test/resources/kotest.properties +2 -0
  33. package/dist/module/GraniteVideo.js +458 -0
  34. package/dist/module/GraniteVideo.js.map +1 -0
  35. package/dist/module/GraniteVideoNativeComponent.ts +265 -0
  36. package/dist/module/index.js +7 -0
  37. package/dist/module/index.js.map +1 -0
  38. package/dist/module/package.json +1 -0
  39. package/dist/module/types.js +4 -0
  40. package/dist/module/types.js.map +1 -0
  41. package/dist/typescript/GraniteVideo.d.ts +12 -0
  42. package/dist/typescript/GraniteVideoNativeComponent.d.ts +189 -0
  43. package/dist/typescript/index.d.ts +5 -0
  44. package/dist/typescript/types.d.ts +328 -0
  45. package/ios/GraniteVideoComponentsProvider.h +10 -0
  46. package/ios/GraniteVideoProvider.swift +280 -0
  47. package/ios/GraniteVideoView.h +15 -0
  48. package/ios/GraniteVideoView.mm +661 -0
  49. package/ios/Providers/AVPlayerProvider.swift +541 -0
  50. package/package.json +106 -0
  51. package/src/GraniteVideo.tsx +575 -0
  52. package/src/GraniteVideoNativeComponent.ts +265 -0
  53. package/src/index.ts +8 -0
  54. package/src/types.ts +464 -0
@@ -0,0 +1,104 @@
1
+ package run.granite.video.provider.media3.listener
2
+
3
+ import androidx.media3.common.PlaybackException
4
+ import androidx.media3.common.Player
5
+ import androidx.media3.common.VideoSize
6
+ import androidx.media3.common.util.UnstableApi
7
+ import run.granite.video.provider.GraniteVideoDelegate
8
+ import run.granite.video.provider.GraniteVideoErrorData
9
+ import run.granite.video.provider.GraniteVideoLoadData
10
+
11
+ /**
12
+ * Callback interface for playback state changes.
13
+ */
14
+ interface PlaybackStateProvider {
15
+ val isPlaying: Boolean
16
+ val isSeeking: Boolean
17
+ val isLooping: Boolean
18
+ val currentTime: Double
19
+ val duration: Double
20
+ }
21
+
22
+ /**
23
+ * ExoPlayer event listener that delegates events to GraniteVideoDelegate.
24
+ * Separated from ExoPlayerProvider for testability.
25
+ */
26
+ @UnstableApi
27
+ class ExoPlayerEventListener(
28
+ private val delegateProvider: () -> GraniteVideoDelegate?,
29
+ private val stateProvider: PlaybackStateProvider,
30
+ private val onPlayingChanged: (Boolean) -> Unit = {},
31
+ private val onVideoSizeChanged: (Int, Int) -> Unit = { _, _ -> }
32
+ ) : Player.Listener {
33
+
34
+ private val delegate: GraniteVideoDelegate?
35
+ get() = delegateProvider()
36
+
37
+ override fun onPlaybackStateChanged(playbackState: Int) {
38
+ when (playbackState) {
39
+ Player.STATE_IDLE -> {
40
+ delegate?.onIdle()
41
+ }
42
+ Player.STATE_BUFFERING -> {
43
+ delegate?.onBuffer(true)
44
+ }
45
+ Player.STATE_READY -> {
46
+ delegate?.onBuffer(false)
47
+ delegate?.onReadyForDisplay()
48
+ delegate?.onLoad(
49
+ GraniteVideoLoadData(
50
+ currentTime = stateProvider.currentTime,
51
+ duration = stateProvider.duration,
52
+ naturalWidth = 0.0, // Will be updated in onVideoSizeChanged
53
+ naturalHeight = 0.0,
54
+ orientation = "landscape"
55
+ )
56
+ )
57
+ }
58
+ Player.STATE_ENDED -> {
59
+ delegate?.onEnd()
60
+ }
61
+ }
62
+ }
63
+
64
+ override fun onIsPlayingChanged(isPlaying: Boolean) {
65
+ onPlayingChanged(isPlaying)
66
+ delegate?.onPlaybackStateChanged(
67
+ isPlaying = isPlaying,
68
+ isSeeking = stateProvider.isSeeking,
69
+ isLooping = stateProvider.isLooping
70
+ )
71
+ }
72
+
73
+ override fun onPlayerError(error: PlaybackException) {
74
+ delegate?.onError(
75
+ GraniteVideoErrorData(
76
+ code = error.errorCode,
77
+ domain = "ExoPlayer",
78
+ localizedDescription = error.message ?: "Unknown error",
79
+ errorString = error.errorCodeName
80
+ )
81
+ )
82
+ }
83
+
84
+ override fun onVideoSizeChanged(videoSize: VideoSize) {
85
+ val width = videoSize.width
86
+ val height = videoSize.height
87
+
88
+ if (width > 0 && height > 0) {
89
+ onVideoSizeChanged(width, height)
90
+ delegate?.onAspectRatioChanged(width.toDouble(), height.toDouble())
91
+
92
+ // Update load data with actual dimensions
93
+ delegate?.onLoad(
94
+ GraniteVideoLoadData(
95
+ currentTime = stateProvider.currentTime,
96
+ duration = stateProvider.duration,
97
+ naturalWidth = width.toDouble(),
98
+ naturalHeight = height.toDouble(),
99
+ orientation = if (width > height) "landscape" else "portrait"
100
+ )
101
+ )
102
+ }
103
+ }
104
+ }
@@ -0,0 +1,56 @@
1
+ package run.granite.video.provider.media3.scheduler
2
+
3
+ import android.os.Handler
4
+ import android.os.Looper
5
+
6
+ /**
7
+ * Interface for scheduling periodic progress updates.
8
+ * Abstracted to allow for testability.
9
+ */
10
+ interface ProgressScheduler {
11
+ /**
12
+ * Schedule a periodic action.
13
+ * @param intervalMs The interval in milliseconds.
14
+ * @param action The action to execute periodically.
15
+ */
16
+ fun schedule(intervalMs: Long, action: () -> Unit)
17
+
18
+ /**
19
+ * Cancel any scheduled actions.
20
+ */
21
+ fun cancel()
22
+ }
23
+
24
+ /**
25
+ * Default implementation using Android Handler.
26
+ */
27
+ class HandlerProgressScheduler(
28
+ private val handler: Handler = Handler(Looper.getMainLooper())
29
+ ) : ProgressScheduler {
30
+
31
+ private var runnable: Runnable? = null
32
+ private var intervalMs: Long = 0
33
+ private var action: (() -> Unit)? = null
34
+
35
+ override fun schedule(intervalMs: Long, action: () -> Unit) {
36
+ cancel()
37
+
38
+ this.intervalMs = intervalMs
39
+ this.action = action
40
+
41
+ runnable = object : Runnable {
42
+ override fun run() {
43
+ action()
44
+ handler.postDelayed(this, intervalMs)
45
+ }
46
+ }
47
+
48
+ handler.post(runnable!!)
49
+ }
50
+
51
+ override fun cancel() {
52
+ runnable?.let { handler.removeCallbacks(it) }
53
+ runnable = null
54
+ action = null
55
+ }
56
+ }