import { Ionicons, MaterialIcons } from "@expo/vector-icons"; import type { BaseItemDto, MediaSourceInfo, } from "@jellyfin/sdk/lib/generated-client"; import { useRouter } from "expo-router"; import { type Dispatch, type FC, type SetStateAction } from "react"; import { Platform, TouchableOpacity, useWindowDimensions, View, } from "react-native"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useHaptic } from "@/hooks/useHaptic"; import { useSettings, VideoPlayer } from "@/utils/atoms/settings"; import { ICON_SIZES } from "./constants"; import { VideoProvider } from "./contexts/VideoContext"; import DropdownView from "./dropdown/DropdownView"; import { type ScaleFactor, ScaleFactorSelector } from "./ScaleFactorSelector"; import { type AspectRatio, AspectRatioSelector, } from "./VideoScalingModeSelector"; interface HeaderControlsProps { item: BaseItemDto; showControls: boolean; offline: boolean; mediaSource?: MediaSourceInfo | null; startPictureInPicture?: () => Promise; switchOnEpisodeMode: () => void; goToPreviousItem: () => void; goToNextItem: (options: { isAutoPlay?: boolean }) => void; previousItem?: BaseItemDto | null; nextItem?: BaseItemDto | null; getAudioTracks?: (() => Promise) | (() => any[]); getSubtitleTracks?: (() => Promise) | (() => any[]); setAudioTrack?: (index: number) => void; setSubtitleTrack?: (index: number) => void; setSubtitleURL?: (url: string, customName: string) => void; aspectRatio?: AspectRatio; scaleFactor?: ScaleFactor; setAspectRatio?: Dispatch>; setScaleFactor?: Dispatch>; setVideoAspectRatio?: (aspectRatio: string | null) => Promise; setVideoScaleFactor?: (scaleFactor: number) => Promise; } export const HeaderControls: FC = ({ item, showControls, offline, mediaSource, startPictureInPicture, switchOnEpisodeMode, goToPreviousItem, goToNextItem, previousItem, nextItem, getAudioTracks, getSubtitleTracks, setAudioTrack, setSubtitleTrack, setSubtitleURL, aspectRatio = "default", scaleFactor = 1.0, setAspectRatio, setScaleFactor, setVideoAspectRatio, setVideoScaleFactor, }) => { const { settings } = useSettings(); const router = useRouter(); const insets = useSafeAreaInsets(); const { width: screenWidth } = useWindowDimensions(); const lightHapticFeedback = useHaptic("light"); const handleAspectRatioChange = async (newRatio: AspectRatio) => { if (!setAspectRatio || !setVideoAspectRatio) return; setAspectRatio(newRatio); const aspectRatioString = newRatio === "default" ? null : newRatio; await setVideoAspectRatio(aspectRatioString); }; const handleScaleFactorChange = async (newScale: ScaleFactor) => { if (!setScaleFactor || !setVideoScaleFactor) return; setScaleFactor(newScale); await setVideoScaleFactor(newScale); }; const onClose = async () => { lightHapticFeedback(); router.back(); }; return ( {!Platform.isTV && (!offline || !mediaSource?.TranscodingUrl) && ( )} {!Platform.isTV && (settings.defaultPlayer === VideoPlayer.VLC_4 || Platform.OS === "android") && ( )} {item?.Type === "Episode" && ( )} {previousItem && ( )} {nextItem && ( goToNextItem({ isAutoPlay: false })} className='aspect-square flex flex-col rounded-xl items-center justify-center p-2' > )} ); };