File size: 1,735 Bytes
5c6cc05 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
import React, {
createContext,
useContext,
useRef,
useState,
useCallback,
} from "react";
// The shape of our context
type TimeContextType = {
currentTime: number;
setCurrentTime: (t: number) => void;
subscribe: (cb: (t: number) => void) => () => void;
isPlaying: boolean;
setIsPlaying: React.Dispatch<React.SetStateAction<boolean>>;
duration: number;
setDuration: React.Dispatch<React.SetStateAction<number>>;
};
const TimeContext = createContext<TimeContextType | undefined>(undefined);
export const useTime = () => {
const ctx = useContext(TimeContext);
if (!ctx) throw new Error("useTime must be used within a TimeProvider");
return ctx;
};
export const TimeProvider: React.FC<{
children: React.ReactNode;
duration: number;
}> = ({ children, duration: initialDuration }) => {
const [currentTime, setCurrentTime] = useState(0);
const [isPlaying, setIsPlaying] = useState(false);
const [duration, setDuration] = useState(initialDuration);
const listeners = useRef<Set<(t: number) => void>>(new Set());
// Call this to update time and notify all listeners
const updateTime = useCallback((t: number) => {
setCurrentTime(t);
listeners.current.forEach((fn) => fn(t));
}, []);
// Components can subscribe to time changes (for imperative updates)
const subscribe = useCallback((cb: (t: number) => void) => {
listeners.current.add(cb);
return () => listeners.current.delete(cb);
}, []);
return (
<TimeContext.Provider
value={{
currentTime,
setCurrentTime: updateTime,
subscribe,
isPlaying,
setIsPlaying,
duration,
setDuration,
}}
>
{children}
</TimeContext.Provider>
);
};
|