import React, { useEffect, useCallback, useState, useRef } from 'react'; import { Sequencer } from './components/Sequencer'; import { useDrumMachine } from './hooks/useDrumMachine'; import { useSession } from './hooks/useSession'; import { useWebSocket } from './hooks/useWebSocket'; import { useCursors } from './hooks/useCursors'; import { ShareIcon, CursorIcon } from './components/icons'; function App(): React.ReactNode { const sessionId = useSession(); const { lastMessage, sendMessage, isConnected, isSynchronized, clientId } = useWebSocket(sessionId); const drumMachine = useDrumMachine(lastMessage, sendMessage); const mainRef = useRef(null); const cursors = useCursors(sendMessage, lastMessage, clientId, mainRef); const { isPlaying, startPlayback, stopPlayback } = drumMachine; const [showCopyMessage, setShowCopyMessage] = useState(false); const handleKeyDown = useCallback((event: KeyboardEvent) => { if (event.code === 'Space' && isSynchronized) { event.preventDefault(); if (isPlaying) { stopPlayback(); } else { startPlayback(); } } }, [isPlaying, startPlayback, stopPlayback, isSynchronized]); useEffect(() => { window.addEventListener('keydown', handleKeyDown); return () => { window.removeEventListener('keydown', handleKeyDown); }; }, [handleKeyDown]); const handleShareSession = () => { navigator.clipboard.writeText(window.location.href).then(() => { setShowCopyMessage(true); setTimeout(() => setShowCopyMessage(false), 3000); }); }; return (

AG Beats

Craft your beats and bass lines with this interactive step sequencer.

{isConnected ? '● Connected' : '● Disconnected'}
{showCopyMessage && (
Session link copied. Send it to your friends!
)}
{Object.values(cursors).map((cursor: any) => (
))} {isSynchronized ? ( ) : (

Synchronizing session state...

)}
); } export default App;