voicebot-react-native-expo
Version:
This is a voicebot-react-native package of Kipps AI voice bot for React Native Expo
94 lines (84 loc) • 3.21 kB
text/typescript
import type { TrackIdentifier } from '@livekit/components-core';
import { isTrackReference } from '@livekit/components-core';
import { setupMediaTrack, log, isLocal, getTrackByIdentifier } from '@livekit/components-core';
import * as React from 'react';
import { mergeProps } from '../utils';
/** @public */
export interface UseMediaTrackOptions {
element?: React.RefObject<HTMLMediaElement> | null;
props?: React.HTMLAttributes<HTMLVideoElement | HTMLAudioElement>;
}
/**
* @internal
*/
export function useMediaTrackBySourceOrName(
observerOptions: TrackIdentifier,
options: UseMediaTrackOptions = {},
) {
const [publication, setPublication] = React.useState(getTrackByIdentifier(observerOptions));
const [isMuted, setMuted] = React.useState(publication?.isMuted);
const [isSubscribed, setSubscribed] = React.useState(publication?.isSubscribed);
const [track, setTrack] = React.useState(publication?.track);
const [orientation, setOrientation] = React.useState<'landscape' | 'portrait'>('landscape');
const previousElement = React.useRef<HTMLMediaElement | undefined | null>();
const { className, trackObserver } = React.useMemo(() => {
return setupMediaTrack(observerOptions);
}, [
observerOptions.participant.sid ?? observerOptions.participant.identity,
observerOptions.source,
isTrackReference(observerOptions) && observerOptions.publication.trackSid,
]);
React.useEffect(() => {
const subscription = trackObserver.subscribe((publication) => {
log.debug('update track', publication);
setPublication(publication);
setMuted(publication?.isMuted);
setSubscribed(publication?.isSubscribed);
setTrack(publication?.track);
});
return () => subscription?.unsubscribe();
}, [trackObserver]);
React.useEffect(() => {
if (track) {
if (previousElement.current) {
track.detach(previousElement.current);
}
if (
options.element?.current &&
!(isLocal(observerOptions.participant) && track?.kind === 'audio')
) {
track.attach(options.element.current);
}
}
previousElement.current = options.element?.current;
return () => {
if (previousElement.current) {
track?.detach(previousElement.current);
}
};
}, [track, options.element]);
React.useEffect(() => {
// Set the orientation of the video track.
// TODO: This does not handle changes in orientation after a track got published (e.g when rotating a phone camera from portrait to landscape).
if (
typeof publication?.dimensions?.width === 'number' &&
typeof publication?.dimensions?.height === 'number'
) {
const orientation_ =
publication.dimensions.width > publication.dimensions.height ? 'landscape' : 'portrait';
setOrientation(orientation_);
}
}, [publication]);
return {
publication,
isMuted,
isSubscribed,
track,
elementProps: mergeProps(options.props, {
className,
'data-lk-local-participant': observerOptions.participant.isLocal,
'data-lk-source': publication?.source,
...(publication?.kind === 'video' && { 'data-lk-orientation': orientation }),
}),
};
}