Live video on the AT Protocol
79
fork

Configure Feed

Select the types of activity you want to include in your feed.

at eli/github-skip-darwin 90 lines 2.5 kB view raw
1import React, { useCallback, useMemo, useState } from "react"; 2import { StoreApi } from "zustand"; 3import { PlayerContext } from "./context"; 4import { PlayerState } from "./player-state"; 5import { makePlayerStore } from "./player-store"; 6 7interface PlayerProviderProps { 8 children: React.ReactNode; 9 initialPlayers?: string[]; 10 defaultId?: string; 11} 12 13export const PlayerProvider: React.FC<PlayerProviderProps> = ({ 14 children, 15 initialPlayers = [], 16 defaultId = Math.random().toString(36).slice(8), 17}) => { 18 const [players, setPlayers] = useState<Record<string, StoreApi<PlayerState>>>( 19 () => { 20 // Initialize with any initial player IDs provided 21 const initialPlayerStores: Record<string, StoreApi<PlayerState>> = {}; 22 for (const playerId of initialPlayers) { 23 initialPlayerStores[playerId] = makePlayerStore(playerId); 24 } 25 26 // Always create at least one player by default 27 if (initialPlayers.length === 0) { 28 initialPlayerStores[defaultId] = makePlayerStore(defaultId); 29 } 30 31 return initialPlayerStores; 32 }, 33 ); 34 35 const createPlayer = useCallback((id?: string) => { 36 console.log("Creating new player"); 37 const playerId = id || Math.random().toString(36).slice(8); 38 const playerStore = makePlayerStore(playerId); 39 40 setPlayers((prev) => ({ 41 ...prev, 42 [playerId]: playerStore, 43 })); 44 45 return playerId; 46 }, []); 47 48 const removePlayer = useCallback((id: string) => { 49 setPlayers((prev) => { 50 // Don't remove the last player 51 if (Object.keys(prev).length <= 1) { 52 console.warn("Cannot remove the last player"); 53 return prev; 54 } 55 56 const newPlayers = { ...prev }; 57 delete newPlayers[id]; 58 return newPlayers; 59 }); 60 }, []); 61 62 const contextValue = useMemo( 63 () => ({ 64 players, 65 createPlayer, 66 removePlayer, 67 }), 68 [players, createPlayer, removePlayer], 69 ); 70 71 return ( 72 <PlayerContext.Provider value={contextValue}> 73 {children} 74 </PlayerContext.Provider> 75 ); 76}; 77 78// HOC to wrap components that need player context 79export function withPlayerProvider<P extends object>( 80 Component: React.ComponentType<P>, 81): React.FC<P & { initialPlayers?: string[] }> { 82 return function WithPlayerProvider(props: P & { initialPlayers?: string[] }) { 83 const { initialPlayers, ...componentProps } = props; 84 return ( 85 <PlayerProvider initialPlayers={initialPlayers}> 86 <Component {...(componentProps as P)} /> 87 </PlayerProvider> 88 ); 89 }; 90}