import { useEffect, useRef, useState } from "react"; import { Countdown } from "../comps/timer"; import { Conversation } from "./conversation"; import { Status, useChat } from "../util/useChat"; const EmojiType={ phone: '๐Ÿ“ž', headphone: '๐ŸŽง', speaker: '๐Ÿ”Š', chat: '๐Ÿ’ฌ', } export function Flow(){ const [cuelist, setCuelist] = useState([]); const [currentCue, setCurrentCue] = useState(null); const [chatWelcome, setChatWelcome] = useState(null); const refTimer=useRef(); const refAudio=useRef(); const refInput=useRef(); const { history, status, reset, sendMessage, setStatus, audioOutput, setAudioOutput, stop:stopChat }=useChat(); function playCue(cue) { if(!cue) return; console.log('Playing cue:', cue); setCurrentCue(cue); if(parseFloat(cue.id)<=4.1){ // Special case for starting a conversation console.log('clear conversation...'); reset(); } if(cue.type=='chat' && cue.id=='4.1'){ // Special case for starting a conversation console.log('Starting conversation...'); sendMessage(); setChatWelcome(true); } 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) return; console.log('onCueEnd:', cue.id); if(cue.type=='chat'){ // sendChatMessage const message= refInput.current.value?.trim(); if(message && message.length>0) { sendMessage(message); setChatWelcome(false); }else{ // if no message, just continue to next cue console.log('No message to send, continuing to next cue'); playCue(cuelist.find(c => c.id === cue.nextcue)); } }else{ if(cue.auto) { playCue(cuelist.find(c => c.id === cue.nextcue)); } } } function onStop(){ console.log('Stopping current cue'); if(refAudio.current) { refAudio.current.pause(); refAudio.current = null; } setCurrentCue(null); refTimer.current.restart(0); stopChat(); // Stop chat processing } useEffect(()=>{ switch(status) { case Status.SUCCESS: console.log('Success!'); setStatus(Status.IDLE); refInput.current.value = '' if(chatWelcome) { return; } // play next cue if(currentCue.nextcue!=5 && currentCue.nextcue!=6){ // Q5 & Q6 wait for audio end if(currentCue.nextcue) { playCue(cuelist.find(c => c.id === currentCue.nextcue)); } else { setCurrentCue(null); } } break; case Status.AUDIO_ENDED: console.log('Audio ended'); if(currentCue.nextcue==5 || currentCue.nextcue==6){ // Q5 & Q6 wait for audio end playCue(cuelist.find(c => c.id === currentCue.nextcue)); } break; } },[status]); 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 (
{currentCue?.name}
{/* */} {cuelist?.map(({id, name, description, type, auto, audioFile,...props}, index) => ( {/* */} ))}
IDName Description Type Auto Audio / Due
{id}{name} {description} {EmojiType[type]} {auto ? 'โคต๏ธ' : ''} {audioFile || props.duration}
{history?.map((msg, index) => (
{msg.content}
{msg.prompt &&
{msg.prompt}
}
))}
setAudioOutput(e.target.checked)} />
chat_status= {status}
); }