|
|
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
|
|
|
|
import { Countdown } from "../comps/timer";
|
|
|
|
|
|
|
|
|
|
|
|
export function Flow(){
|
|
|
|
|
|
|
|
|
|
|
|
const [cuelist, setCuelist] = useState([]);
|
|
|
|
|
|
const [currentCue, setCurrentCue] = useState(null);
|
|
|
|
|
|
const refTimer=useRef();
|
|
|
|
|
|
const refAudio=useRef();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function playCue(cue) {
|
|
|
|
|
|
|
|
|
|
|
|
if(!cue) return;
|
|
|
|
|
|
console.log('Playing cue:', cue);
|
|
|
|
|
|
setCurrentCue(cue.name);
|
|
|
|
|
|
|
|
|
|
|
|
if(cue.audioFile){
|
|
|
|
|
|
// Stop any currently playing audio
|
|
|
|
|
|
if(refAudio.current) {
|
|
|
|
|
|
refAudio.current.pause();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const audio = new Audio(cue.audioFile);
|
|
|
|
|
|
|
|
|
|
|
|
if(cue.loop){
|
|
|
|
|
|
audio.loop = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
audio.play().catch(error => {
|
|
|
|
|
|
console.error('Error playing audio:', error);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
audio.onended = () => {
|
|
|
|
|
|
onCueEnd(cue);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
refAudio.current = audio;
|
|
|
|
|
|
audio.addEventListener("loadedmetadata", () => {
|
|
|
|
|
|
refTimer.current.restart(audio.duration*1000 || 0);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
if(cue.duration){
|
|
|
|
|
|
refTimer.current.restart(cue.duration*1000, ()=>{
|
|
|
|
|
|
onCueEnd(cue);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function onCueEnd(cue) {
|
|
|
|
|
|
if(cue.auto) {
|
|
|
|
|
|
playCue(cuelist.find(c => c.id === cue.id+1));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function onStop(){
|
|
|
|
|
|
console.log('Stopping current cue');
|
|
|
|
|
|
if(refAudio.current) {
|
|
|
|
|
|
refAudio.current.pause();
|
|
|
|
|
|
refAudio.current = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
setCurrentCue(null);
|
|
|
|
|
|
refTimer.current.restart(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(()=>{
|
|
|
|
|
|
fetch('/cuelist.json')
|
|
|
|
|
|
.then(response => response.json())
|
|
|
|
|
|
.then(data => {
|
|
|
|
|
|
console.log('Cuelist data:', data);
|
|
|
|
|
|
setCuelist(data.cuelist);
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(error => {
|
|
|
|
|
|
console.error('Error fetching cuelist:', error);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
},[]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<main className="items-center">
|
|
|
|
|
|
|
|
|
|
|
|
<div className="w-full p-2 flex flex-row justify-center gap-2 *:w-[10vw] *:h-[10vw]">
|
|
|
|
|
|
<div className="bg-gray-100 text-4xl font-bold mb-4 flex justify-center items-center">
|
|
|
|
|
|
{currentCue}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<Countdown ref={refTimer} />
|
|
|
|
|
|
<button className="bg-red-300 border-0 font-bold uppercase"
|
|
|
|
|
|
onClick={onStop}>Stop</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<table className="border-collapse **:border-y w-full **:p-2">
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
<tr className="text-left">
|
|
|
|
|
|
{/* <th>ID</th> */}
|
|
|
|
|
|
<th>Name</th>
|
|
|
|
|
|
<th>Description</th>
|
|
|
|
|
|
<th>Type</th>
|
|
|
|
|
|
<th>Auto</th>
|
|
|
|
|
|
<th>Audio File</th>
|
|
|
|
|
|
<th></th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
{cuelist?.map(({id, name, description, type, auto, audioFile,...props}, index) => (
|
|
|
|
|
|
<tr key={id}>
|
|
|
|
|
|
{/* <td>{id}</td> */}
|
|
|
|
|
|
<td>{name}</td>
|
|
|
|
|
|
<td>{description}</td>
|
|
|
|
|
|
<td>{type=='phone'?'📞':(type=='headphone'?'🎧':'🔊')}</td>
|
|
|
|
|
|
<td>{auto ? '↩️' : ''}</td>
|
|
|
|
|
|
<td>{audioFile}</td>
|
|
|
|
|
|
<td>
|
|
|
|
|
|
<button className="rounded-full border-none bg-green-200"
|
|
|
|
|
|
onClick={()=>{
|
|
|
|
|
|
playCue({id, name, description, type, auto, audioFile, ...props});
|
|
|
|
|
|
}}>go</button>
|
|
|
|
|
|
</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</main>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|