mirror of
https://github.com/zoriya/react-native-omni.git
synced 2026-08-16 02:44:51 +00:00
fix(web): make source a listenable state, fixes the view
This commit is contained in:
@@ -55,6 +55,9 @@ export function usePlayerState<Key extends keyof OmniPlayerState>(
|
||||
case "castStatus":
|
||||
em.addCastStatusListener(setState);
|
||||
return () => em.removeCastStatusListener(setState);
|
||||
case "source":
|
||||
em.addSourceListener(setState);
|
||||
return () => em.removeSourceListener(setState);
|
||||
}
|
||||
}, [player, key]);
|
||||
|
||||
|
||||
+14
-3
@@ -12,7 +12,7 @@ import {
|
||||
selectVolume,
|
||||
usePlayer as useStoreSelector,
|
||||
} from "@videojs/react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, useSyncExternalStore } from "react";
|
||||
import type { WebOmniPlayer } from "./player.web";
|
||||
import { usePlayer } from "./provider.web";
|
||||
import type { OmniEvents } from "./types/events";
|
||||
@@ -204,6 +204,7 @@ export const stateMapper = {
|
||||
}),
|
||||
};
|
||||
|
||||
// biome-ignore-start lint/correctness/useHookAtTopLevel: key must be const
|
||||
export function usePlayerState<Key extends keyof OmniPlayerState>(
|
||||
key: Key,
|
||||
): OmniPlayerState[Key];
|
||||
@@ -215,8 +216,18 @@ export function usePlayerState<Key extends keyof OmniPlayerState>(
|
||||
key: Key,
|
||||
_refresh?: number,
|
||||
): OmniPlayerState[Key] {
|
||||
const config = stateMapper[key];
|
||||
if (key === "source") {
|
||||
const player = usePlayer() as WebOmniPlayer;
|
||||
const source = useSyncExternalStore(
|
||||
player.subscribeSource,
|
||||
() => player.source,
|
||||
() => player.source,
|
||||
);
|
||||
return source as OmniPlayerState[Key];
|
||||
}
|
||||
const config = stateMapper[key as keyof Omit<OmniPlayerState, "source">];
|
||||
const ret = useStoreSelector(config?.selector as Selector<any, any>);
|
||||
if (!config) throw new Error(`No mapper for ${key}`);
|
||||
const ret = useStoreSelector(config.selector as Selector<any, any>);
|
||||
return config.mapper(ret) as OmniPlayerState[Key];
|
||||
}
|
||||
// biome-ignore-end lint/correctness/useHookAtTopLevel: key must be const
|
||||
|
||||
@@ -70,6 +70,13 @@ export class WebOmniPlayer implements OmniPlayer {
|
||||
private overlaySubtitle: Subtitle | null = null;
|
||||
private overlayListeners = new Set<() => void>();
|
||||
|
||||
private sourceListeners = new Set<() => void>();
|
||||
subscribeSource = (callback: () => void): (() => void) => {
|
||||
this.sourceListeners.add(callback);
|
||||
return () => this.sourceListeners.delete(callback);
|
||||
};
|
||||
|
||||
|
||||
get source(): Source | undefined {
|
||||
return this._source;
|
||||
}
|
||||
@@ -84,6 +91,7 @@ export class WebOmniPlayer implements OmniPlayer {
|
||||
this.setOverlaySubtitle(null);
|
||||
}
|
||||
this.updateMediaSession();
|
||||
for (const listener of this.sourceListeners) listener();
|
||||
}
|
||||
|
||||
get showNotification(): boolean {
|
||||
|
||||
@@ -11,7 +11,7 @@ import type { CastOptions, Source } from "../types/source";
|
||||
|
||||
export type NumberProperty = Exclude<
|
||||
keyof OmniPlayerState,
|
||||
"status" | "isPlaying" | "muted"
|
||||
"status" | "isPlaying" | "muted" | "source"
|
||||
>;
|
||||
export type BoolProperty = "isPlaying" | "muted" | "isAutoQuality";
|
||||
|
||||
@@ -29,6 +29,9 @@ export interface OmniEventMap extends HybridObject<{ android: "kotlin" }> {
|
||||
addCastStatusListener(cb: (value: CastStatus) => void): void;
|
||||
removeCastStatusListener(cb: (value: CastStatus) => void): void;
|
||||
|
||||
addSourceListener(cb: (value?: Source) => void): void;
|
||||
removeSourceListener(cb: (value?: Source) => void): void;
|
||||
|
||||
addOnEndListener(cb: OmniEvents["end"]): void;
|
||||
removeOnEndListener(cb: OmniEvents["end"]): void;
|
||||
|
||||
|
||||
+1
-2
@@ -3,8 +3,6 @@ import type { Source } from "./source";
|
||||
export interface OmniPlayer extends OmniPlayerState {
|
||||
showNotification?: boolean;
|
||||
|
||||
source?: Source;
|
||||
|
||||
play(): void;
|
||||
pause(): void;
|
||||
seekBy(offset: number): void;
|
||||
@@ -28,6 +26,7 @@ export interface OmniPlayer extends OmniPlayerState {
|
||||
}
|
||||
|
||||
export interface OmniPlayerState {
|
||||
source?: Source;
|
||||
readonly status: PlayerStatus;
|
||||
readonly isPlaying: boolean;
|
||||
currentTime: number;
|
||||
|
||||
+11
-11
@@ -109,18 +109,18 @@ export const OmniView = ({
|
||||
const player = usePlayer() as WebOmniPlayer;
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const ref = useRef<HTMLVideoElement>(undefined!);
|
||||
const source = usePlayerState("source");
|
||||
|
||||
const src = player.source?.src;
|
||||
const isHls =
|
||||
src?.mimeType?.toLowerCase().includes("mpegurl") ||
|
||||
src?.uri.split(/[?#]/)[0]?.toLowerCase().endsWith(".m3u8") ||
|
||||
source?.src?.mimeType?.toLowerCase().includes("mpegurl") ||
|
||||
source?.src?.uri.split(/[?#]/)[0]?.toLowerCase().endsWith(".m3u8") ||
|
||||
false;
|
||||
const Tech = isHls ? HlsJsVideo : Video;
|
||||
|
||||
const headersRef = useRef(src?.headers);
|
||||
headersRef.current = src?.headers;
|
||||
const castId = player.source?.castId;
|
||||
const castData = player.source?.castData;
|
||||
const headersRef = useRef(source?.src?.headers);
|
||||
headersRef.current = source?.src?.headers;
|
||||
const castId = source?.castId;
|
||||
const castData = source?.castData;
|
||||
|
||||
const config = useMemo<HlsMediaConfig>(
|
||||
() => ({
|
||||
@@ -151,17 +151,17 @@ export const OmniView = ({
|
||||
ref={containerRef}
|
||||
style={{ position: "relative", ...style }}
|
||||
>
|
||||
{src && (
|
||||
{source?.src && (
|
||||
<Tech
|
||||
ref={ref}
|
||||
src={src.uri}
|
||||
src={source?.src.uri}
|
||||
config={config}
|
||||
autoPlay={autoplay}
|
||||
playsInline
|
||||
crossOrigin="anonymous"
|
||||
style={{ width: "100%", height: "100%", objectFit: "contain" }}
|
||||
>
|
||||
{(player.source?.subtitles ?? []).map((subtitle) => (
|
||||
{(source?.subtitles ?? []).map((subtitle) => (
|
||||
<track
|
||||
key={subtitle.id}
|
||||
id={subtitle.id}
|
||||
@@ -177,7 +177,7 @@ export const OmniView = ({
|
||||
<SubtitleOverlay
|
||||
video={ref}
|
||||
assets={subtitleAssets}
|
||||
fonts={player.source?.fonts}
|
||||
fonts={source?.fonts}
|
||||
/>
|
||||
)}
|
||||
</VideoPlayer.Container>
|
||||
|
||||
Reference in New Issue
Block a user