wip: Implement events

This commit is contained in:
2026-04-10 23:28:46 +02:00
parent 626380bcc4
commit f6721de3a6
36 changed files with 1824 additions and 111 deletions
+31
View File
@@ -0,0 +1,31 @@
import { useEffect, useState } from "react";
import { usePlayer } from "./provider";
import type { OmniPlayer } from "./specs/omni-player.nitro";
import type { OmniEvents } from "./types/events";
import type { OmniPlayerState } from "./types/player";
function capitalize<T extends string>(str: T): Capitalize<T> {
return (str.charAt(0).toUpperCase() +
str.slice(1).toLowerCase()) as Capitalize<T>;
}
export const useEvent = <Event extends keyof OmniEvents>(
event: Event,
callback: OmniEvents[Event],
) => {
const player = usePlayer() as OmniPlayer;
useEffect(() => {
player.eventMap[`addOn${capitalize(event)}Listener`](callback as any);
return () =>
player.eventMap[`removeOn${capitalize(event)}Listener`](callback as any);
}, [player, event, callback]);
};
export const usePlayerState = <Key extends keyof OmniPlayerState>(
key: Key,
): OmniPlayerState[Key] => {
const player = usePlayer();
const [ret, setState] = useState(player[key]);
// TODO: find a way to listen to that.
return ret;
};
+2
View File
@@ -0,0 +1,2 @@
export { OmniProvider, usePlayer } from "./provider";
export { OmniView } from "./view";
+43 -2
View File
@@ -1,10 +1,51 @@
import type { HybridObject } from "react-native-nitro-modules";
import type { OmniPlayer as OmniPlayerT } from "../types/player";
import type { OmniEvents } from "../types/events";
import type {
OmniPlayerState,
OmniPlayer as OmniPlayerT,
} from "../types/player";
import type { Source } from "../types/source";
export interface OmniEventMap extends HybridObject<{ android: "kotlin" }> {
addStateListener(
key: keyof OmniPlayerState,
cb: (value: number) => void,
): void;
removeStateListener(cb: OmniEvents["end"]): void;
addOnEndListener(cb: OmniEvents["end"]): void;
removeOnEndListener(cb: OmniEvents["end"]): void;
addOnPrevListener(cb: OmniEvents["prev"]): void;
removeOnPrevListener(cb: OmniEvents["prev"]): void;
addOnNextListener(cb: OmniEvents["next"]): void;
removeOnNextListener(cb: OmniEvents["next"]): void;
addOnErrorListener(cb: OmniEvents["error"]): void;
removeOnErrorListener(cb: OmniEvents["error"]): void;
addOnAudioFocusChangeListener(cb: OmniEvents["audioFocusChange"]): void;
removeOnAudioFocusChangeListener(cb: OmniEvents["audioFocusChange"]): void;
addOnVideoTrackChangeListener(cb: OmniEvents["videoTrackChange"]): void;
removeOnVideoTrackChangeListener(cb: OmniEvents["videoTrackChange"]): void;
addOnAudioTrackChangeListener(cb: OmniEvents["audioTrackChange"]): void;
removeOnAudioTrackChangeListener(cb: OmniEvents["audioTrackChange"]): void;
addOnSubtitleChangeListener(cb: OmniEvents["subtitleChange"]): void;
removeOnSubtitleChangeListener(cb: OmniEvents["subtitleChange"]): void;
addOnRenditionChangeListener(cb: OmniEvents["renditionChange"]): void;
removeOnRenditionChangeListener(cb: OmniEvents["renditionChange"]): void;
}
export interface OmniPlayer
extends HybridObject<{ android: "kotlin" }>,
OmniPlayerT {}
OmniPlayerT {
readonly eventMap: OmniEventMap;
}
export interface OmniPlayerFactory extends HybridObject<{ android: "kotlin" }> {
createPlayer(props: Source): OmniPlayer;
+15 -1
View File
@@ -1,3 +1,17 @@
import type { Rendition, Track } from "./player";
export interface OmniEvents {
onEnd: () => void;
end: () => void;
prev: () => void;
next: () => void;
error: (type: ErrorType, message: string) => void;
audioFocusChange: (status: AudioFocus) => void;
videoTrackChange: (track: Track) => void;
audioTrackChange: (track: Track) => void;
subtitleChange: (track?: Track) => void;
renditionChange: (rendition: Rendition) => void;
}
export type ErrorType = string;
export type AudioFocus = string;
+12 -10
View File
@@ -1,6 +1,6 @@
import type { Source } from "./source";
export interface OmniPlayer {
export interface OmniPlayer extends OmniPlayerState {
source: Source;
play(): void;
@@ -13,15 +13,6 @@ export interface OmniPlayer {
readonly hasPrev: boolean;
readonly hasNext: boolean;
readonly status: PlayerStatus;
readonly isPlaying: boolean;
currentTime: number;
readonly buffered: number;
readonly duration: number;
playbackRate: number;
// between 0 and 1
volume: number;
readonly videos: Track[];
selectVideo(video: Track): void;
readonly audios: Track[];
@@ -32,6 +23,17 @@ export interface OmniPlayer {
selectRendition(rendition?: Rendition): void;
}
export interface OmniPlayerState {
readonly status: PlayerStatus;
readonly isPlaying: boolean;
currentTime: number;
readonly buffered: number;
readonly duration: number;
playbackRate: number;
// between 0 and 1
volume: number;
}
export type PlayerStatus = "idle" | "loading" | "readyToPlay" | "error";
export interface Track {