Skip to content

Commit

Permalink
add another type
Browse files Browse the repository at this point in the history
  • Loading branch information
haileyok committed Sep 4, 2024
1 parent 7d66f12 commit 737b5d2
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 43 deletions.
94 changes: 56 additions & 38 deletions patches/expo-video+1.2.4.patch
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ index 473f964..f37aff9 100644
@@ -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)
Expand All @@ -32,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)
Expand Down Expand Up @@ -86,24 +86,24 @@ index 4b6c6d8..e20f51a 100644
+++ b/node_modules/expo-video/android/src/main/java/expo/modules/video/VideoManager.kt
@@ -1,5 +1,6 @@
package expo.modules.video

+import android.provider.MediaStore.Video
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
import expo.modules.kotlin.AppContext
@@ -15,6 +16,8 @@ object VideoManager {
// Keeps track of all existing VideoPlayers, and whether they are attached to a VideoView
private var videoPlayersToVideoViews = mutableMapOf<VideoPlayer, MutableList<VideoView>>()

+ private var previouslyPlayingViews: MutableList<VideoView>? = null
+
private lateinit var audioFocusManager: AudioFocusManager

fun onModuleCreated(appContext: AppContext) {
@@ -69,16 +72,24 @@ object VideoManager {
return videoPlayersToVideoViews[videoPlayer]?.isNotEmpty() ?: false
}

- fun onAppForegrounded() = Unit
+ fun onAppForegrounded() {
+ val previouslyPlayingViews = this.previouslyPlayingViews ?: return
Expand All @@ -113,7 +113,7 @@ index 4b6c6d8..e20f51a 100644
+ }
+ this.previouslyPlayingViews = null
+ }

fun onAppBackgrounded() {
+ val previouslyPlayingViews = mutableListOf<VideoView>()
for (videoView in videoViews.values) {
Expand Down Expand Up @@ -144,15 +144,15 @@ 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
Expand All @@ -162,18 +162,18 @@ index 58f00af..5ad8237 100644
.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
Expand All @@ -184,7 +184,7 @@ index 58f00af..5ad8237 100644
@@ -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
Expand Down Expand Up @@ -224,7 +224,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
Expand All @@ -234,17 +234,17 @@ 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)
videoPlayer?.changePlayerView(playerView)
+ 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..5eac9e5 100644
index a09fcfe..46cbae7 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 = {
Expand All @@ -256,6 +256,15 @@ index a09fcfe..5eac9e5 100644
};
/**
* Describes the current status of the player.
@@ -136,7 +138,7 @@ export type VideoPlayerEvents = {
* - `readyToPlay`: The player has loaded enough data to start playing or to continue playback.
* - `error`: The player has encountered an error while loading or playing the video.
*/
-export type VideoPlayerStatus = 'idle' | 'loading' | 'readyToPlay' | 'error';
+export type VideoPlayerStatus = 'idle' | 'loading' | 'readyToPlay' | 'error' | 'waitingToPlayAtSpecifiedRate';
export type VideoSource = string | {
/**
* The URI of the video.
diff --git a/node_modules/expo-video/build/VideoView.types.d.ts b/node_modules/expo-video/build/VideoView.types.d.ts
index cb9ca6d..ed8bb7e 100644
--- a/node_modules/expo-video/build/VideoView.types.d.ts
Expand Down Expand Up @@ -288,11 +297,11 @@ index 094a8b0..16e7081 100644
--- a/node_modules/expo-video/ios/VideoManager.swift
+++ b/node_modules/expo-video/ios/VideoManager.swift
@@ -12,6 +12,7 @@ class VideoManager {

private var videoViews = NSHashTable<VideoView>.weakObjects()
private var videoPlayers = NSHashTable<VideoPlayer>.weakObjects()
+ private var previouslyPlayingPlayers: [VideoPlayer]?

func register(videoPlayer: VideoPlayer) {
videoPlayers.add(videoPlayer)
@@ -33,63 +34,70 @@ class VideoManager {
Expand All @@ -306,7 +315,7 @@ index 094a8b0..16e7081 100644
+ }
+ }
}

func onAppBackgrounded() {
+ var previouslyPlayingPlayers: [VideoPlayer] = []
for videoView in videoViews.allObjects {
Expand All @@ -323,9 +332,9 @@ index 094a8b0..16e7081 100644
}
+ self.previouslyPlayingPlayers = previouslyPlayingPlayers
}

// MARK: - Audio Session Management

internal func setAppropriateAudioSessionOrWarn() {
- let audioSession = AVAudioSession.sharedInstance()
- var audioSessionCategoryOptions: AVAudioSession.CategoryOptions = []
Expand Down Expand Up @@ -422,7 +431,7 @@ 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..733ab1f 100644
Expand All @@ -431,7 +440,7 @@ index 3315b88..733ab1f 100644
@@ -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)
+ }
Expand All @@ -449,22 +458,22 @@ index d289e26..7de8cbf 100644
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 {
Expand All @@ -475,7 +484,7 @@ index d289e26..7de8cbf 100644
+ player?.removeTimeObserver(playerPeriodicTimeObserver)
+ }
}

private func initializeCurrentPlayerItemObservers(player: AVPlayer, playerItem: AVPlayerItem) {
@@ -265,23 +271,24 @@ class VideoPlayerObserver {
if player.timeControlStatus != .waitingToPlayAtSpecifiedRate && player.status == .readyToPlay && currentItem?.isPlaybackBufferEmpty != true {
Expand All @@ -484,20 +493,20 @@ index d289e26..7de8cbf 100644
- status = .loading
+ status = .waitingToPlayAtSpecifiedRate
}

if isPlaying != (player.timeControlStatus == .playing) {
isPlaying = player.timeControlStatus == .playing
+ addPeriodicTimeObserverIfNeeded()
}
}

private func onIsBufferEmptyChanged(_ playerItem: AVPlayerItem, _ change: NSKeyValueObservedChange<Bool>) {
if playerItem.isPlaybackBufferEmpty {
- status = .loading
+ status = .playbackBufferEmpty
}
}

private func onPlayerLikelyToKeepUpChanged(_ playerItem: AVPlayerItem, _ change: NSKeyValueObservedChange<Bool>) {
if !playerItem.isPlaybackLikelyToKeepUp && playerItem.isPlaybackBufferEmpty {
- status = .loading
Expand Down Expand Up @@ -539,12 +548,12 @@ 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 {
Expand All @@ -554,7 +563,7 @@ index f4579e4..10c5908 100644
+ onEnterFullscreen()
isFullscreen = true
}

@@ -179,6 +182,7 @@ public final class VideoView: ExpoView, AVPlayerViewControllerDelegate {
if wasPlaying {
self.player?.pointer.play()
Expand All @@ -564,7 +573,7 @@ index f4579e4..10c5908 100644
}
}
diff --git a/node_modules/expo-video/src/VideoPlayer.types.ts b/node_modules/expo-video/src/VideoPlayer.types.ts
index aaf4b63..f438196 100644
index aaf4b63..5ff6b7a 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 = {
Expand All @@ -574,8 +583,17 @@ index aaf4b63..f438196 100644
+
+ timeRemainingChange(timeRemaining: number): void;
};

/**
@@ -160,7 +162,7 @@ export type VideoPlayerEvents = {
* - `readyToPlay`: The player has loaded enough data to start playing or to continue playback.
* - `error`: The player has encountered an error while loading or playing the video.
*/
-export type VideoPlayerStatus = 'idle' | 'loading' | 'readyToPlay' | 'error';
+export type VideoPlayerStatus = 'idle' | 'loading' | 'readyToPlay' | 'error' | 'waitingToPlayAtSpecifiedRate';

export type VideoSource =
| string
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
Expand Down
18 changes: 13 additions & 5 deletions src/view/com/util/post-embeds/VideoEmbed.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, {useCallback, useEffect, useId, useState} from 'react'
import {View} from 'react-native'
import {Image} from 'expo-image'
import {VideoPlayerStatus} from 'expo-video'
import {AppBskyEmbedVideo} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
Expand Down Expand Up @@ -67,14 +68,15 @@ function Inner({embed}: Props) {
useActiveVideoNative()
const viewId = useId()

const [playerStatus, setPlayerStatus] = useState<
'loading' | 'idle' | 'readyToPlay' | 'error'
>('loading')
const [playerStatus, setPlayerStatus] = useState<VideoPlayerStatus>('loading')
const [isMuted, setIsMuted] = useState(player.muted)
const [isFullscreen, setIsFullscreen] = React.useState(false)
const [timeRemaining, setTimeRemaining] = React.useState(0)
const isActive = embed.playlist === activeSource && activeViewId === viewId
const isLoading = isActive && playerStatus === 'loading'
const isLoading =
isActive &&
(playerStatus === 'waitingToPlayAtSpecifiedRate' ||
playerStatus === 'loading')

useEffect(() => {
if (isActive) {
Expand Down Expand Up @@ -105,6 +107,12 @@ function Inner({embed}: Props) {
}
}, [player, isActive])

useEffect(() => {
if (!isActive && playerStatus !== 'loading') {
setPlayerStatus('loading')
}
}, [isActive, playerStatus])

const onChangeStatus = (isVisible: boolean) => {
if (isFullscreen) {
return
Expand Down Expand Up @@ -159,7 +167,7 @@ function Inner({embed}: Props) {
}}
label={_(msg`Play video`)}
color="secondary">
{playerStatus === 'loading' ? (
{isLoading ? (
<View
style={[
a.rounded_full,
Expand Down

0 comments on commit 737b5d2

Please sign in to comment.