about summary refs log tree commit diff
path: root/patches
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-08-29 08:28:41 -0700
committerGitHub <noreply@github.com>2024-08-29 08:28:41 -0700
commitd52d29621e0f5df9cba16795d40db8a413248342 (patch)
tree2ec7666e527605cb8606037e448f340e93ba5ffd /patches
parentd92731b1ebf006ab795cf726452a7f15a49ba618 (diff)
downloadvoidsky-d52d29621e0f5df9cba16795d40db8a413248342.tar.zst
[Video] Add `timeRemainingChange` event to `player` in `expo-video` (#5013)
Diffstat (limited to 'patches')
-rw-r--r--patches/expo-video+1.2.4.patch269
1 files changed, 258 insertions, 11 deletions
diff --git a/patches/expo-video+1.2.4.patch b/patches/expo-video+1.2.4.patch
index 918c8a8d2..a159f7e5d 100644
--- a/patches/expo-video+1.2.4.patch
+++ b/patches/expo-video+1.2.4.patch
@@ -1,3 +1,27 @@
+diff --git a/node_modules/expo-video/android/src/main/java/expo/modules/video/PlayerEvent.kt b/node_modules/expo-video/android/src/main/java/expo/modules/video/PlayerEvent.kt
+index 473f964..f37aff9 100644
+--- a/node_modules/expo-video/android/src/main/java/expo/modules/video/PlayerEvent.kt
++++ b/node_modules/expo-video/android/src/main/java/expo/modules/video/PlayerEvent.kt
+@@ -41,6 +41,11 @@ sealed class PlayerEvent {
+     override val name = "playToEnd"
+   }
+
++  data class PlayerTimeRemainingChanged(val timeRemaining: Double): PlayerEvent() {
++    override val name = "timeRemainingChange"
++    override val arguments = arrayOf(timeRemaining)
++  }
++
+   fun emit(player: VideoPlayer, listeners: List<VideoPlayerListener>) {
+     when (this) {
+       is StatusChanged -> listeners.forEach { it.onStatusChanged(player, status, oldStatus, error) }
+@@ -49,6 +54,7 @@ sealed class PlayerEvent {
+       is SourceChanged -> listeners.forEach { it.onSourceChanged(player, source, oldSource) }
+       is PlaybackRateChanged -> listeners.forEach { it.onPlaybackRateChanged(player, rate, oldRate) }
+       is PlayedToEnd -> listeners.forEach { it.onPlayedToEnd(player) }
++      is PlayerTimeRemainingChanged -> listeners.forEach { it.onPlayerTimeRemainingChanged(player, timeRemaining) }
+     }
+   }
+ }
 diff --git a/node_modules/expo-video/android/src/main/java/expo/modules/video/PlayerViewExtension.kt b/node_modules/expo-video/android/src/main/java/expo/modules/video/PlayerViewExtension.kt
 index 9905e13..47342ff 100644
 --- a/node_modules/expo-video/android/src/main/java/expo/modules/video/PlayerViewExtension.kt
@@ -8,10 +32,10 @@ index 9905e13..47342ff 100644
    setTimeBarInteractive(requireLinearPlayback)
 +  setShowSubtitleButton(true)
  }
- 
+
  @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
 @@ -27,7 +28,8 @@ internal fun PlayerView.setTimeBarInteractive(interactive: Boolean) {
- 
+
  @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
  internal fun PlayerView.setFullscreenButtonVisibility(visible: Boolean) {
 -  val fullscreenButton = findViewById<android.widget.ImageButton>(androidx.media3.ui.R.id.exo_fullscreen)
@@ -20,6 +44,42 @@ index 9905e13..47342ff 100644
    fullscreenButton?.visibility = if (visible) {
      android.view.View.VISIBLE
    } else {
+diff --git a/node_modules/expo-video/android/src/main/java/expo/modules/video/ProgressTracker.kt b/node_modules/expo-video/android/src/main/java/expo/modules/video/ProgressTracker.kt
+new file mode 100644
+index 0000000..0249e23
+--- /dev/null
++++ b/node_modules/expo-video/android/src/main/java/expo/modules/video/ProgressTracker.kt
+@@ -0,0 +1,29 @@
++import android.os.Handler
++import android.os.Looper
++import androidx.annotation.OptIn
++import androidx.media3.common.util.UnstableApi
++import expo.modules.video.PlayerEvent
++import expo.modules.video.VideoPlayer
++import kotlin.math.floor
++
++@OptIn(UnstableApi::class)
++class ProgressTracker(private val videoPlayer: VideoPlayer) : Runnable {
++  private val handler: Handler = Handler(Looper.getMainLooper())
++  private val player = videoPlayer.player
++
++  init {
++    handler.post(this)
++  }
++
++  override fun run() {
++    val currentPosition = player.currentPosition
++    val duration = player.duration
++    val timeRemaining = floor(((duration - currentPosition) / 1000).toDouble())
++    videoPlayer.sendEvent(PlayerEvent.PlayerTimeRemainingChanged(timeRemaining))
++    handler.postDelayed(this, 1000 /* ms */)
++  }
++
++  fun remove() {
++    handler.removeCallbacks(this)
++  }
++}
+\ No newline at end of file
 diff --git a/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoModule.kt b/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoModule.kt
 index ec3da2a..5a1397a 100644
 --- a/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoModule.kt
@@ -33,8 +93,76 @@ index ec3da2a..5a1397a 100644
 +        "onEnterFullscreen",
 +        "onExitFullscreen"
        )
- 
+
        Prop("player") { view: VideoView, player: VideoPlayer ->
+diff --git a/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayer.kt b/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayer.kt
+index 58f00af..5ad8237 100644
+--- a/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayer.kt
++++ b/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayer.kt
+@@ -1,5 +1,6 @@
+ package expo.modules.video
+
++import ProgressTracker
+ import android.content.Context
+ import android.view.SurfaceView
+ import androidx.media3.common.MediaItem
+@@ -35,11 +36,13 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
+     .Builder(context, renderersFactory)
+     .setLooper(context.mainLooper)
+     .build()
++  var progressTracker: ProgressTracker? = null
+
+   val serviceConnection = PlaybackServiceConnection(WeakReference(player))
+
+   var playing by IgnoreSameSet(false) { new, old ->
+     sendEvent(PlayerEvent.IsPlayingChanged(new, old))
++    addOrRemoveProgressTracker()
+   }
+
+   var uncommittedSource: VideoSource? = source
+@@ -141,6 +144,9 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
+   }
+
+   override fun close() {
++    this.progressTracker?.remove()
++    this.progressTracker = null
++
+     appContext?.reactContext?.unbindService(serviceConnection)
+     serviceConnection.playbackServiceBinder?.service?.unregisterPlayer(player)
+     VideoManager.unregisterVideoPlayer(this@VideoPlayer)
+@@ -228,7 +234,7 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
+     listeners.removeAll { it.get() == videoPlayerListener }
+   }
+
+-  private fun sendEvent(event: PlayerEvent) {
++  fun sendEvent(event: PlayerEvent) {
+     // Emits to the native listeners
+     event.emit(this, listeners.mapNotNull { it.get() })
+     // Emits to the JS side
+@@ -240,4 +246,13 @@ class VideoPlayer(val context: Context, appContext: AppContext, source: VideoSou
+       sendEvent(eventName, *args)
+     }
+   }
++
++  private fun addOrRemoveProgressTracker() {
++    this.progressTracker?.remove()
++    if (this.playing) {
++      this.progressTracker = ProgressTracker(this)
++    } else {
++      this.progressTracker = null
++    }
++  }
+ }
+diff --git a/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayerListener.kt b/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayerListener.kt
+index f654254..dcfe3f0 100644
+--- a/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayerListener.kt
++++ b/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoPlayerListener.kt
+@@ -15,4 +15,5 @@ interface VideoPlayerListener {
+   fun onSourceChanged(player: VideoPlayer, source: VideoSource?, oldSource: VideoSource?) {}
+   fun onPlaybackRateChanged(player: VideoPlayer, rate: Float, oldRate: Float?) {}
+   fun onPlayedToEnd(player: VideoPlayer) {}
++  fun onPlayerTimeRemainingChanged(player: VideoPlayer, timeRemaining: Double) {}
+ }
 diff --git a/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoView.kt b/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoView.kt
 index a951d80..3932535 100644
 --- a/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoView.kt
@@ -45,7 +173,7 @@ index a951d80..3932535 100644
    val onPictureInPictureStop by EventDispatcher<Unit>()
 +  val onEnterFullscreen by EventDispatcher()
 +  val onExitFullscreen by EventDispatcher()
- 
+
    var willEnterPiP: Boolean = false
    var isInFullscreen: Boolean = false
 @@ -154,6 +156,7 @@ class VideoView(context: Context, appContext: AppContext) : ExpoView(context, ap
@@ -55,7 +183,7 @@ index a951d80..3932535 100644
 +    onEnterFullscreen(mapOf())
      isInFullscreen = true
    }
- 
+
 @@ -162,6 +165,7 @@ class VideoView(context: Context, appContext: AppContext) : ExpoView(context, ap
      val fullScreenButton: ImageButton = playerView.findViewById(androidx.media3.ui.R.id.exo_fullscreen)
      fullScreenButton.setImageResource(androidx.media3.ui.R.drawable.exo_icon_fullscreen_enter)
@@ -63,9 +191,22 @@ index a951d80..3932535 100644
 +    this.onExitFullscreen(mapOf())
      isInFullscreen = false
    }
- 
+
+diff --git a/node_modules/expo-video/build/VideoPlayer.types.d.ts b/node_modules/expo-video/build/VideoPlayer.types.d.ts
+index a09fcfe..65fe29a 100644
+--- a/node_modules/expo-video/build/VideoPlayer.types.d.ts
++++ b/node_modules/expo-video/build/VideoPlayer.types.d.ts
+@@ -128,6 +128,8 @@ export type VideoPlayerEvents = {
+      * Handler for an event emitted when the current media source of the player changes.
+      */
+     sourceChange(newSource: VideoSource, previousSource: VideoSource): void;
++
++    timeRemainingChange(timeRemaining: number): void;
+ };
+ /**
+  * Describes the current status of the player.
 diff --git a/node_modules/expo-video/build/VideoView.types.d.ts b/node_modules/expo-video/build/VideoView.types.d.ts
-index cb9ca6d..60e9f4e 100644
+index cb9ca6d..ed8bb7e 100644
 --- a/node_modules/expo-video/build/VideoView.types.d.ts
 +++ b/node_modules/expo-video/build/VideoView.types.d.ts
 @@ -89,5 +89,8 @@ export interface VideoViewProps extends ViewProps {
@@ -77,6 +218,7 @@ index cb9ca6d..60e9f4e 100644
 +    onExitFullscreen?: () => void;
  }
  //# sourceMappingURL=VideoView.types.d.ts.map
+\ No newline at end of file
 diff --git a/node_modules/expo-video/ios/VideoModule.swift b/node_modules/expo-video/ios/VideoModule.swift
 index c537a12..e4a918f 100644
 --- a/node_modules/expo-video/ios/VideoModule.swift
@@ -90,19 +232,111 @@ index c537a12..e4a918f 100644
 +        "onEnterFullscreen",
 +        "onExitFullscreen"
        )
- 
+
        Prop("player") { (view, player: VideoPlayer?) in
+diff --git a/node_modules/expo-video/ios/VideoPlayer.swift b/node_modules/expo-video/ios/VideoPlayer.swift
+index 3315b88..f482390 100644
+--- a/node_modules/expo-video/ios/VideoPlayer.swift
++++ b/node_modules/expo-video/ios/VideoPlayer.swift
+@@ -185,6 +185,10 @@ internal final class VideoPlayer: SharedRef<AVPlayer>, Hashable, VideoPlayerObse
+     safeEmit(event: "sourceChange", arguments: newVideoPlayerItem?.videoSource, oldVideoPlayerItem?.videoSource)
+   }
+
++  func onPlayerTimeRemainingChanged(player: AVPlayer, timeRemaining: Double) {
++    safeEmit(event: "timeRemainingChange", arguments: timeRemaining)
++  }
++
+   func safeEmit<each A: AnyArgument>(event: String, arguments: repeat each A) {
+     if self.appContext != nil {
+       self.emit(event: event, arguments: repeat each arguments)
+diff --git a/node_modules/expo-video/ios/VideoPlayerObserver.swift b/node_modules/expo-video/ios/VideoPlayerObserver.swift
+index d289e26..d0fdd30 100644
+--- a/node_modules/expo-video/ios/VideoPlayerObserver.swift
++++ b/node_modules/expo-video/ios/VideoPlayerObserver.swift
+@@ -21,6 +21,7 @@ protocol VideoPlayerObserverDelegate: AnyObject {
+   func onItemChanged(player: AVPlayer, oldVideoPlayerItem: VideoPlayerItem?, newVideoPlayerItem: VideoPlayerItem?)
+   func onIsMutedChanged(player: AVPlayer, oldIsMuted: Bool?, newIsMuted: Bool)
+   func onPlayerItemStatusChanged(player: AVPlayer, oldStatus: AVPlayerItem.Status?, newStatus: AVPlayerItem.Status)
++  func onPlayerTimeRemainingChanged(player: AVPlayer, timeRemaining: Double)
+ }
+
+ // Default implementations for the delegate
+@@ -33,6 +34,7 @@ extension VideoPlayerObserverDelegate {
+   func onItemChanged(player: AVPlayer, oldVideoPlayerItem: VideoPlayerItem?, newVideoPlayerItem: VideoPlayerItem?) {}
+   func onIsMutedChanged(player: AVPlayer, oldIsMuted: Bool?, newIsMuted: Bool) {}
+   func onPlayerItemStatusChanged(player: AVPlayer, oldStatus: AVPlayerItem.Status?, newStatus: AVPlayerItem.Status) {}
++  func onPlayerTimeRemainingChanged(player: AVPlayer, timeRemaining: Double) {}
+ }
+
+ // Wrapper used to store WeakReferences to the observer delegate
+@@ -91,6 +93,7 @@ class VideoPlayerObserver {
+   private var playerVolumeObserver: NSKeyValueObservation?
+   private var playerCurrentItemObserver: NSKeyValueObservation?
+   private var playerIsMutedObserver: NSKeyValueObservation?
++  private var playerPeriodicTimeObserver: Any?
+
+   // Current player item observers
+   private var playbackBufferEmptyObserver: NSKeyValueObservation?
+@@ -152,6 +155,9 @@ class VideoPlayerObserver {
+     playerVolumeObserver?.invalidate()
+     playerIsMutedObserver?.invalidate()
+     playerCurrentItemObserver?.invalidate()
++    if let playerPeriodicTimeObserver = self.playerPeriodicTimeObserver {
++      player?.removeTimeObserver(playerPeriodicTimeObserver)
++    }
+   }
+
+   private func initializeCurrentPlayerItemObservers(player: AVPlayer, playerItem: AVPlayerItem) {
+@@ -270,6 +276,7 @@ class VideoPlayerObserver {
+
+     if isPlaying != (player.timeControlStatus == .playing) {
+       isPlaying = player.timeControlStatus == .playing
++      addOrRemovePeriodicTimeObserver()
+     }
+   }
+
+@@ -310,4 +317,30 @@ class VideoPlayerObserver {
+       }
+     }
+   }
++
++  private func onPlayerTimeRemainingChanged(_ player: AVPlayer, _ timeRemaining: Double) {
++    delegates.forEach { delegate in
++      delegate.value?.onPlayerTimeRemainingChanged(player: player, timeRemaining: timeRemaining)
++    }
++  }
++
++  private func addOrRemovePeriodicTimeObserver() {
++    guard let player = self.player else {
++      return
++    }
++
++    if isPlaying {
++      // Add the time update listener
++      playerPeriodicTimeObserver = player.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1.0, preferredTimescale: Int32(NSEC_PER_SEC)), queue: nil) { event in
++        guard let duration = player.currentItem?.duration else {
++          return
++        }
++
++        let timeRemaining = (duration.seconds - event.seconds).rounded()
++        self.onPlayerTimeRemainingChanged(player, timeRemaining)
++      }
++    } else if let playerPeriodicTimeObserver = self.playerPeriodicTimeObserver {
++      player.removeTimeObserver(playerPeriodicTimeObserver)
++    }
++  }
+ }
 diff --git a/node_modules/expo-video/ios/VideoView.swift b/node_modules/expo-video/ios/VideoView.swift
 index f4579e4..10c5908 100644
 --- a/node_modules/expo-video/ios/VideoView.swift
 +++ b/node_modules/expo-video/ios/VideoView.swift
 @@ -41,6 +41,8 @@ public final class VideoView: ExpoView, AVPlayerViewControllerDelegate {
- 
+
    let onPictureInPictureStart = EventDispatcher()
    let onPictureInPictureStop = EventDispatcher()
 +  let onEnterFullscreen = EventDispatcher()
 +  let onExitFullscreen = EventDispatcher()
- 
+
    public override var bounds: CGRect {
      didSet {
 @@ -163,6 +165,7 @@ public final class VideoView: ExpoView, AVPlayerViewControllerDelegate {
@@ -112,7 +346,7 @@ index f4579e4..10c5908 100644
 +    onEnterFullscreen()
      isFullscreen = true
    }
- 
+
 @@ -179,6 +182,7 @@ public final class VideoView: ExpoView, AVPlayerViewControllerDelegate {
          if wasPlaying {
            self.player?.pointer.play()
@@ -121,6 +355,19 @@ index f4579e4..10c5908 100644
          self.isFullscreen = false
        }
      }
+diff --git a/node_modules/expo-video/src/VideoPlayer.types.ts b/node_modules/expo-video/src/VideoPlayer.types.ts
+index aaf4b63..f438196 100644
+--- a/node_modules/expo-video/src/VideoPlayer.types.ts
++++ b/node_modules/expo-video/src/VideoPlayer.types.ts
+@@ -151,6 +151,8 @@ export type VideoPlayerEvents = {
+    * Handler for an event emitted when the current media source of the player changes.
+    */
+   sourceChange(newSource: VideoSource, previousSource: VideoSource): void;
++
++  timeRemainingChange(timeRemaining: number): void;
+ };
+
+ /**
 diff --git a/node_modules/expo-video/src/VideoView.types.ts b/node_modules/expo-video/src/VideoView.types.ts
 index 29fe5db..e1fbf59 100644
 --- a/node_modules/expo-video/src/VideoView.types.ts