Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ import { TPStreamsPlayerView } from "react-native-tpstreams";

- `onError(error: {message: string, code: number, details?: string})`: Fires when an error occurs.

- `onAccessTokenExpired(videoId: string, callback: (newToken: string) => void)`: Fires when the access token expires. Call the callback with a new token to continue playback.
Comment thread
Gowreesh-A-M marked this conversation as resolved.

---

## Player Props
Expand Down Expand Up @@ -173,6 +175,11 @@ function TPStreamsPlayerExample() {
onPlaybackSpeedChanged={(speed) => console.log(`Speed changed: ${speed}x`)}
onIsLoadingChanged={(isLoading) => console.log(`Loading: ${isLoading}`)}
onError={(error) => console.error('Player error:', error)}
onAccessTokenExpired={async (videoId, callback) => {
// Fetch a new token from your server
const newToken = await getNewTokenForVideo(videoId);
callback(newToken);
}}
/>

<Button title="Play" onPress={handlePlay} />
Expand Down
21 changes: 21 additions & 0 deletions android/src/main/java/com/tpstreams/TPStreamsRNPlayerView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class TPStreamsRNPlayerView(context: ThemedReactContext) : FrameLayout(context)
private var startAt: Long = 0
private var showDefaultCaptions: Boolean = false
private var enableDownload: Boolean = false
private var accessTokenCallback: ((String) -> Unit)? = null

init {
addView(playerView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
Expand Down Expand Up @@ -76,6 +77,14 @@ class TPStreamsRNPlayerView(context: ThemedReactContext) : FrameLayout(context)
fun setEnableDownload(enableDownload: Boolean) {
this.enableDownload = enableDownload
}

fun setNewAccessToken(newToken: String) {
Log.d("TPStreamsRNPlayerView", "Setting new access token")
accessTokenCallback?.let { callback ->
callback(newToken)
accessTokenCallback = null
} ?: Log.w("TPStreamsRNPlayerView", "No callback available for token refresh")
}

fun tryCreatePlayer() {
if (videoId.isNullOrEmpty() || accessToken.isNullOrEmpty()) return
Expand All @@ -92,6 +101,17 @@ class TPStreamsRNPlayerView(context: ThemedReactContext) : FrameLayout(context)
showDefaultCaptions
)

player?.listener = object : TPStreamsPlayer.Listener {
override fun onAccessTokenExpired(videoId: String, callback: (String) -> Unit) {
if (accessTokenCallback != null) {
Log.w("TPStreamsRNPlayerView", "onAccessTokenExpired called while another refresh is in progress. Ignoring.")
return
}
accessTokenCallback = callback
emitEvent("onAccessTokenExpired", mapOf("videoId" to videoId))
}
}

// Add player event listeners
player?.addListener(createPlayerListener())

Expand Down Expand Up @@ -188,5 +208,6 @@ class TPStreamsRNPlayerView(context: ThemedReactContext) : FrameLayout(context)
Log.e("TPStreamsRN", "Error releasing player", e)
}
player = null
accessTokenCallback = null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class TPStreamsRNPlayerViewManager : SimpleViewManager<TPStreamsRNPlayerView>(),
private const val EVENT_PLAYBACK_SPEED_CHANGED = "onPlaybackSpeedChanged"
private const val EVENT_IS_LOADING_CHANGED = "onIsLoadingChanged"
private const val EVENT_ERROR = "onError"
private const val EVENT_ACCESS_TOKEN_EXPIRED = "onAccessTokenExpired"
}

private val mDelegate: ViewManagerDelegate<TPStreamsRNPlayerView> =
Expand All @@ -46,6 +47,7 @@ class TPStreamsRNPlayerViewManager : SimpleViewManager<TPStreamsRNPlayerView>(),
.put(EVENT_PLAYBACK_SPEED_CHANGED, MapBuilder.of("registrationName", EVENT_PLAYBACK_SPEED_CHANGED))
.put(EVENT_IS_LOADING_CHANGED, MapBuilder.of("registrationName", EVENT_IS_LOADING_CHANGED))
.put(EVENT_ERROR, MapBuilder.of("registrationName", EVENT_ERROR))
.put(EVENT_ACCESS_TOKEN_EXPIRED, MapBuilder.of("registrationName", EVENT_ACCESS_TOKEN_EXPIRED))
.build()
}

Expand Down Expand Up @@ -115,6 +117,10 @@ class TPStreamsRNPlayerViewManager : SimpleViewManager<TPStreamsRNPlayerView>(),
view.getPlaybackSpeed()
}

override fun setNewAccessToken(view: TPStreamsRNPlayerView, newToken: String) {
view.setNewAccessToken(newToken)
}

override fun onAfterUpdateTransaction(view: TPStreamsRNPlayerView) {
super.onAfterUpdateTransaction(view)
view.tryCreatePlayer()
Expand Down
22 changes: 22 additions & 0 deletions src/TPStreamsPlayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export interface TPStreamsPlayerProps extends ViewProps {
code: number;
details?: string;
}) => void;
onAccessTokenExpired?: (
videoId: string,
callback: (newToken: string) => void
) => void;
}

/**
Expand All @@ -71,6 +75,7 @@ const TPStreamsPlayerView = forwardRef<
onPlaybackSpeedChanged,
onIsLoadingChanged,
onError,
onAccessTokenExpired,
...restProps
} = props;

Expand Down Expand Up @@ -160,6 +165,22 @@ const TPStreamsPlayerView = forwardRef<
[onError]
);

const handleAccessTokenExpired = useCallback(
(event: { nativeEvent: { videoId: string } }) => {
if (onAccessTokenExpired) {
const { videoId: expiredVideoId } = event.nativeEvent;
onAccessTokenExpired(expiredVideoId, (newToken: string) => {
if (nativeRef.current) {
Commands.setNewAccessToken(nativeRef.current, newToken);
} else {
console.error('[RN] Native ref is not available');
}
});
}
},
[onAccessTokenExpired]
);

// Helper to create promise-based API methods
const createPromiseMethod = useCallback(
(command: (ref: any) => void, eventKey: string) => {
Expand Down Expand Up @@ -225,6 +246,7 @@ const TPStreamsPlayerView = forwardRef<
onPlaybackSpeedChanged: handlePlaybackSpeedChanged,
onIsLoadingChanged: handleIsLoadingChanged,
onError: handleError,
onAccessTokenExpired: handleAccessTokenExpired,
};

return <TPStreamsPlayerNative {...nativeProps} ref={nativeRef} />;
Expand Down
6 changes: 6 additions & 0 deletions src/TPStreamsPlayerViewNativeComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export interface NativeProps extends ViewProps {
onPlaybackSpeedChanged?: DirectEventHandler<{ speed: Double }>;
onIsLoadingChanged?: DirectEventHandler<{ isLoading: boolean }>;
onError?: DirectEventHandler<ErrorEvent>;
onAccessTokenExpired?: DirectEventHandler<{ videoId: string }>;
}

interface TPStreamsPlayerViewCommands {
Expand All @@ -56,6 +57,10 @@ interface TPStreamsPlayerViewCommands {
getPlaybackSpeed: (
viewRef: React.ElementRef<HostComponent<NativeProps>>
) => void;
setNewAccessToken: (
viewRef: React.ElementRef<HostComponent<NativeProps>>,
newToken: string
) => void;
}

export const Commands = codegenNativeCommands<TPStreamsPlayerViewCommands>({
Expand All @@ -68,6 +73,7 @@ export const Commands = codegenNativeCommands<TPStreamsPlayerViewCommands>({
'getDuration',
'isPlaying',
'getPlaybackSpeed',
'setNewAccessToken',
],
});

Expand Down
Loading