134 lines
4.8 KiB
TypeScript
134 lines
4.8 KiB
TypeScript
import React, { useEffect, useState, useRef } from 'react';
|
|
import Box from '@mui/material/Box';
|
|
import PropagateLoader from 'react-spinners/PropagateLoader';
|
|
import { Quote } from 'components/Quote';
|
|
import { BackstoryElementProps } from 'components/BackstoryTab';
|
|
import { useUser } from 'hooks/useUser';
|
|
import { Candidate, ChatSession } from 'types/types';
|
|
import { useSecureAuth } from 'hooks/useSecureAuth';
|
|
|
|
interface GenerateImageProps extends BackstoryElementProps {
|
|
prompt: string;
|
|
chatSession: ChatSession;
|
|
};
|
|
|
|
const GenerateImage = (props: GenerateImageProps) => {
|
|
const { user } = useSecureAuth();
|
|
const { setSnack, chatSession, prompt } = props;
|
|
const [processing, setProcessing] = useState<boolean>(false);
|
|
const [status, setStatus] = useState<string>('');
|
|
const [image, setImage] = useState<string>('');
|
|
|
|
const name = (user?.userType === 'candidate' ? (user as Candidate).username : user?.email) || '';
|
|
// Only keep refs that are truly necessary
|
|
const controllerRef = useRef<string>(null);
|
|
|
|
// Effect to trigger profile generation when user data is ready
|
|
useEffect(() => {
|
|
if (controllerRef.current) {
|
|
console.log("Controller already active, skipping profile generation");
|
|
return;
|
|
}
|
|
if (!prompt) {
|
|
return;
|
|
}
|
|
setStatus('Starting image generation...');
|
|
setProcessing(true);
|
|
const start = Date.now();
|
|
|
|
// controllerRef.current = streamQueryResponse({
|
|
// query: {
|
|
// prompt: prompt,
|
|
// agentOptions: {
|
|
// username: name,
|
|
// }
|
|
// },
|
|
// type: "image",
|
|
// onComplete: (msg) => {
|
|
// switch (msg.status) {
|
|
// case "partial":
|
|
// case "done":
|
|
// if (msg.status === "done") {
|
|
// if (!msg.response) {
|
|
// setSnack("Image generation failed", "error");
|
|
// } else {
|
|
// setImage(msg.response);
|
|
// }
|
|
// setProcessing(false);
|
|
// controllerRef.current = null;
|
|
// }
|
|
// break;
|
|
// case "error":
|
|
// console.log(`Error generating profile: ${msg.response} after ${Date.now() - start}`);
|
|
// setSnack(msg.response || "", "error");
|
|
// setProcessing(false);
|
|
// controllerRef.current = null;
|
|
// break;
|
|
// default:
|
|
// let data: any = {};
|
|
// try {
|
|
// data = typeof msg.response === 'string' ? JSON.parse(msg.response) : msg.response;
|
|
// } catch (e) {
|
|
// data = { message: msg.response };
|
|
// }
|
|
// if (msg.status !== "heartbeat") {
|
|
// console.log(data);
|
|
// }
|
|
// if (data.message) {
|
|
// setStatus(data.message);
|
|
// }
|
|
// break;
|
|
// }
|
|
// }
|
|
// });
|
|
}, [user, prompt, setSnack]);
|
|
|
|
if (!chatSession) {
|
|
return <></>;
|
|
}
|
|
|
|
return (
|
|
<Box className="GenerateImage" sx={{
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
flexGrow: 1,
|
|
gap: 1,
|
|
maxWidth: { xs: '100%', md: '700px', lg: '1024px' },
|
|
minHeight: "max-content",
|
|
}}>
|
|
{image !== '' && <img alt={prompt} src={`${image}/${chatSession.id}`} />}
|
|
{ prompt &&
|
|
<Quote size={processing ? "normal" : "small"} quote={prompt} sx={{ "& *": { color: "#2E2E2E !important" }}}/>
|
|
}
|
|
{processing &&
|
|
<Box sx={{
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
m: 0,
|
|
gap: 1,
|
|
minHeight: "min-content",
|
|
mb: 2
|
|
}}>
|
|
{ status &&
|
|
<Box sx={{ display: "flex", flexDirection: "column"}}>
|
|
<Box sx={{ fontSize: "0.5rem"}}>Generation status</Box>
|
|
<Box sx={{ fontWeight: "bold"}}>{status}</Box>
|
|
</Box>
|
|
}
|
|
<PropagateLoader
|
|
size="10px"
|
|
loading={processing}
|
|
color="white"
|
|
aria-label="Loading Spinner"
|
|
data-testid="loader"
|
|
/>
|
|
</Box>
|
|
}
|
|
</Box>);
|
|
};
|
|
|
|
export {
|
|
GenerateImage
|
|
}; |