import style from './List.module.css'; import { createRef, useCallback, useEffect, useMemo, useState } from 'react'; import { useSocket } from 'app/context/socketContext'; import Empty from 'common/state/Empty'; import EventListItem from './EventListItem'; import { DragDropContext, Droppable } from 'react-beautiful-dnd'; import { useAtom } from 'jotai'; import { SelectSetting } from 'app/context/settingsAtom'; export default function EventList(props) { const { events, eventsHandler } = props; const socket = useSocket(); const [selectedId, setSelectedId] = useState(null); const [nextId, setNextId] = useState(null); const [cursor, setCursor] = useState(0); const [cursorSettings] = useAtom(useMemo(() => SelectSetting('cursor'), [])); const cursorRef = createRef(); // Handle keyboard shortcuts const handleKeyPress = useCallback( (e) => { // Check if the alt key is pressed if (e.altKey) { // Arrow down if (e.keyCode === 40) { if (cursor == null) setCursor(0); else if (cursor < events.length - 1) setCursor(cursor + 1); } // Arrow up if (e.keyCode === 38) { if (cursor == null) setCursor(0); else if (cursor > 0) setCursor(cursor - 1); } // E if (e.key === 'e' || e.key === 'E') { e.preventDefault(); if (cursor == null) return; eventsHandler('add', { type: 'event', order: cursor + 1 }); } // D if (e.key === 'd' || e.key === 'D') { e.preventDefault(); if (cursor == null) return; eventsHandler('add', { type: 'delay', order: cursor + 1 }); } // B if (e.key === 'b' || e.key === 'B') { e.preventDefault(); if (cursor == null) return; eventsHandler('add', { type: 'block', order: cursor + 1 }); } } }, [cursor, events, eventsHandler] ); useEffect(() => { // attach the event listener document.addEventListener('keydown', handleKeyPress); if (cursor > events.length - 1) setCursor(events.length - 1); // remove the event listener return () => { document.removeEventListener('keydown', handleKeyPress); }; }, [handleKeyPress, cursor, events]); // useEffect(() => { // let unsubscribe = tinykeys(window, { // 'Alt+ArrowDown': () => { // if (cursor == null) setCursor(0); // else if (cursor < events.length - 1) setCursor(cursor + 1); // }, // 'Alt+ArrowUp': () => { // if (cursor == null) setCursor(0); // else if (cursor > 0) setCursor(cursor - 1); // }, // 'Alt+KeyE': (event) => { // event.preventDefault(); // if (cursor == null) return; // eventsHandler('add', { type: 'event', order: cursor + 1 }); // }, // 'Alt+KeyD': (event) => { // event.preventDefault(); // if (cursor == null) return; // eventsHandler('add', { type: 'delay', order: cursor + 1 }); // }, // 'Alt+KeyB': (event) => { // event.preventDefault(); // if (cursor == null) return; // eventsHandler('add', { type: 'block', order: cursor + 1 }); // }, // }); // if (cursor > events.length - 1) setCursor(events.length - 1); // return () => { // unsubscribe(); // }; // }, [cursor, events, eventsHandler]); // handle incoming messages useEffect(() => { if (socket == null) return; // ask for playstate socket.emit('get-selected'); socket.emit('get-next-id'); // Handle playstate socket.on('selected', (data) => { setSelectedId(data.id); }); socket.on('next-id', (data) => { setNextId(data); }); // Clear listener return () => { socket.off('selected'); socket.off('next-id'); }; }, [socket]); // when cursor moves, view should follow useEffect(() => { if (cursorRef.current == null) return; cursorRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start', }); }, [cursor]); // if selected event // or cursor settings changed useEffect(() => { // and if we are locked if (cursorSettings !== 'locked' || selectedId == null) return; // move cursor let gotoIndex = -1; let found = false; for (const e of events) { gotoIndex++; if (e.id === selectedId) { found = true; break; } } if (found) { // move cursor setCursor(gotoIndex); } }, [selectedId, cursorSettings]); if (events.length < 1) { return ; } // DND const handleOnDragEnd = (result) => { // drop outside of area if (!result.destination) return; // no change if (result.destination === result.source.index) return; // Call API eventsHandler('reorder', { index: result.draggableId, from: result.source.index, to: result.destination.index, }); }; let cumulativeDelay = 0; let eventIndex = -1; return (
{(provided) => (
{events.map((e, index) => { if (index === 0) { cumulativeDelay = 0; eventIndex = -1; } if (e.type === 'delay' && e.duration != null) { cumulativeDelay += e.duration; } else if (e.type === 'block') { cumulativeDelay = 0; } else if (e.type === 'event') { eventIndex++; } return (
); })} {provided.placeholder}
)}
); }