/** * Shared scrub-preview bubble for the casting progress bars. * * The slider (`react-native-awesome-slider`) sizes, centres and clamps this * bubble on the thumb via its `bubbleMaxWidth` / `bubbleWidth` props. This * component therefore does NO horizontal positioning — it only anchors itself * vertically (`bottom: 0`, growing upward) so it sits above the progress bar. */ import { Image } from "expo-image"; import { View } from "react-native"; import { Text } from "@/components/common/Text"; import type { useTrickplay } from "@/hooks/useTrickplay"; import { formatTrickplayTime } from "@/utils/casting/helpers"; type TrickplayReturn = ReturnType; interface CastTrickplayBubbleProps { /** Current trickplay image URL/coordinates, or null. */ trickPlayUrl: TrickplayReturn["trickPlayUrl"]; /** Parsed trickplay metadata, or null. */ trickplayInfo: TrickplayReturn["trickplayInfo"]; /** Scrub time to display. */ trickplayTime: { hours: number; minutes: number; seconds: number }; /** Trickplay tile width in px (220 main player, 140 mini-player). */ tileWidth: number; } export function CastTrickplayBubble({ trickPlayUrl, trickplayInfo, trickplayTime, tileWidth, }: CastTrickplayBubbleProps) { const timeText = ( {formatTrickplayTime(trickplayTime)} ); // Anchored to the bottom of the slider-positioned container, growing upward, // and filling the container width (left/right: 0) so it stays centred on the // thumb. No horizontal maths here — the slider owns horizontal placement. if (!trickPlayUrl || !trickplayInfo) { return ( {timeText} ); } const { x, y, url } = trickPlayUrl; const tileHeight = tileWidth / (trickplayInfo.aspectRatio ?? 1.78); return ( {timeText} ); }