import { useCallback, useEffect, useRef, useState } from "react"; import { embeddedSubtitles, fetchSubtitles, fileUrl, listSubtitles, openExternal, resolveStream, savePlayback, } from "../api"; import { DEFAULT_SUB_LANG, SUB_FONTS, SUB_PLACES, type FeedItem, type SubStyle } from "../types"; import { compactViews, relativeTime, subtitleLabel } from "./format"; import PlayerControls from "./PlayerControls"; import { Badge, BTN, Dialog, Spinner } from "./ui"; interface Props { item: FeedItem; /** Local file when downloaded; null means resolve and stream it instead. */ path: string | null; onClose: () => void; onDelete: () => void; onPrev?: () => void; onNext?: () => void; /** Present only while streaming, so the video can be saved from here. */ onDownload?: () => void; downloading?: boolean; /** Max height for streaming, or null to let the player adapt. */ maxHeight: number | null; /** Preferred subtitle language, or "off". */ subLang: string; subStyle: SubStyle; onSubStyle: (s: SubStyle) => void; /** Leaves the player for this video's channel. */ onOpenChannel: () => void; /** Roll straight on to the next video when this one ends. */ autoplayNext: boolean; /** Persists a subtitle choice made from the transport bar. */ onSubLang: (l: string) => void; /** Position in the current feed, for the "3 of 180" readout. */ index: number; total: number; /** False in window fullscreen, where there are no traffic lights to clear. */ titleBarInset: boolean; } /** * Releases a