import { useSyncExternalStore, useRef } from 'react'; import { useAviationPlayer } from '../AviationContext'; import { IDLE_POSITION, samePosition } from '../snapshots'; import type { AviationPlayer } from '../Aviation'; import type { MediaPosition } from '../specs/types.nitro'; /** * React hook that subscribes to a player's media position updates. * * Returns a `MediaPosition` struct with current position, duration, * seekable range, live edge info, and progress (0-1). * * Updates at the native time-observer frequency (~250ms for VOD, * ~1s for live). Uses `useSyncExternalStore` for tear-free reads. * * @example * ```tsx * function ProgressBar() { * const { currentMs, durationMs, progress, isLive, isAtLiveEdge } = useMediaPosition(); * return ; * } * ``` */ export function useMediaPosition(playerArg?: AviationPlayer): MediaPosition { const player = useAviationPlayer(playerArg); const store = player.store; const ref = useRef(IDLE_POSITION); const getSnapshot = () => { const pos = store.mediaPosition; const prev = ref.current; if (samePosition(prev, pos)) return prev; ref.current = pos; return ref.current; }; return useSyncExternalStore(store.subscribePosition, getSnapshot); }