/* eslint-disable import/no-duplicates */ import type { VideoProperties } from '@react-native-bedrock/native/react-native-video'; import type VideoRef from '@react-native-bedrock/native/react-native-video'; import { forwardRef, Ref, useMemo, useState } from 'react'; import { Animated, Platform } from 'react-native'; import { Video as RNVideo } from './instance'; import { isAvailable } from './instance'; import { useVisibility } from '../visibility'; const AnimatedRNVideo = Animated.createAnimatedComponent(RNVideo); // Add this interface declaration interface VideoComponent extends React.ForwardRefExoticComponent> { isAvailable: boolean; } /** * @public * @category UI * @name OnAudioFocusChanged * @description 오디오 포커스가 변경될 때 호출되는 콜백 함수에요. `muted` 가 `false` 인 경우에 필수로 구현해야해요. * * @param {Object} event - 오디오 포커스 정보를 담고 있는 이벤트 객체예요. * @param {boolean} event.hasAudioFocus - 비디오 컴포넌트가 오디오 포커스를 가지고 있는지 여부를 나타내요. */ type OnAudioFocusChanged = NonNullable; type Props = | (VideoProperties & { muted: true }) | (VideoProperties & { muted: false; onAudioFocusChanged: OnAudioFocusChanged }); /** * @public * @category UI * @name RNVideoRef * @description * `react-native-video`의 ref 타입이에요. */ export type RNVideoRef = VideoRef; /** * @public * @name Video * @category UI * @description * Video 컴포넌트는 다른 앱에서 음악을 재생 중일 때, 토스 앱에서 그 음악을 중지시키지 않도록 오디오 포커스를 제어하는 로직이 구현된 컴포넌트에요. 앱의 상태에 따라 자동으로 재생하거나 일시정지해요. 예를 들어, 앱이 백그라운드로 전환되면 비디오가 자동으로 일시정지돼요. * * ::: warning * Video 컴포넌트는 [`react-native-video` 버전(6.0.0-alpha.6)](https://github.com/TheWidlarzGroup/react-native-video/tree/v6.0.0-alpha.6) 을 사용하고 있어요. 따라서 일부 타입이나 기능이 최신 버전과 호환되지 않을 수 있어요. * ::: * * @property {boolean} [isAvailable] `Video` 컴포넌트를 사용할 수 있는지 확인하는 값이에요. 이 값을 확인해서 사용자가 비디오를 렌더링할 수 있는지 혹은 환경적 제약(예: 네트워크 연결 문제, 지원되지 않는 디바이스 등)으로 인해 비디오 기능을 사용할 수 없는지를 먼저 확인할 수 있어요. 이 값이 `false`라면, 비디오를 렌더링하지 않거나 대체 콘텐츠를 제공하는 등의 처리를 해야 해요. * * @param {VideoProperties} [props] [`react-native-video`](https://github.com/TheWidlarzGroup/react-native-video/tree/v6.0.0-alpha.6)에서 제공하는 속성들이에요. * @param {string} [props.source.uri] 재생할 비디오의 소스에요. 파일 경로나 URL을 설정할 수 있어요. * @param {boolean} [props.muted=false] 비디오의 음소거 상태를 제어해요. `true`면 비디오의 오디오가 음소거되고, `false`면 오디오가 재생돼요. 기본값은 `false`에요. * @param {boolean} [props.paused=false] 비디오 재생을 제어하는 속성이에요. `true`이면 비디오가 일시 정지되고, `false`이면 비디오가 재생돼요. 기본값은 `false`이고, 자동 재생돼요. * @param {OnAudioFocusChanged} [props.onAudioFocusChanged] 오디오 포커스가 변경될 때 호출되는 콜백 함수에요. `muted` 가 `false` 인 경우에 필수로 구현해야해요. 자세한 내용은 [OnAudioFocusChanged](/react-native/reference/react-native-bedrock/Types/OnAudioFocusChanged.html)를 참고해주세요. * @param {Ref} ref 비디오 인스턴스에 접근하기 위한 ref 객체에요. 이 ref를 통해 비디오 인스턴스의 여러 메서드에 접근할 수 있어요. * * @returns {JSX.Element} 비디오를 렌더링하는 JSX 엘리먼트를 반환해요. `Animated`를 사용해 부드러운 애니메이션 효과를 포함한 비디오 재생을 제공해요. * * @see [react-native-video] https://github.com/react-native-video/react-native-video * 비디오 컴포넌트의 자세한 속성은 공식 문서를 참고해주세요. * @see [react-native-video-6.0.0-alpha.6] https://github.com/TheWidlarzGroup/react-native-video/releases/tag/v6.0.0-alpha.6 * 현재 토스앱에 설치되어있는 버전의 소스코드에요. * * @example * * ### 비디오 자동재생 예제 * * ```tsx * import { useRef } from 'react'; * import { View } from 'react-native'; * import { Video } from 'react-native-bedrock'; * * export function VideoExample() { * const videoRef = useRef(null); * * return ( * * * ); * } * ``` */ export const Video = forwardRef((props: Props, ref: Ref) => { const [isFocused, setIsFocused] = useState(props.muted || props.paused); const visible = useVisibility(); // onAudioFocusChanged로 서비스에서 직접 포커스 상태를 관리하는 경우가 아니라면, 내부 상태를 바탕으로 paused 값을 제어합니다. const paused = useMemo( () => !visible || props.paused || (!props.onAudioFocusChanged && !isFocused), [props.onAudioFocusChanged, props.paused, visible, isFocused] ); const disableFocus = props.muted || props.paused; const mixWithOthers = props.muted ? 'mix' : undefined; return ( setIsFocused(hasAudioFocus)} {...props} enableDecoderFallback={true} paused={paused} mixWithOthers={mixWithOthers} /> ); }); (Video as VideoComponent).isAvailable = isAvailable;