mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 17:58:55 +00:00
accordion update and vd inference panel
This commit is contained in:
1 parent
a12d035be6
commit
ec9f5b8d44
3 files changed
+176
-83
No files matched your search
@@ -44,11 +44,12 @@ function AccordionItem({
|
||||
);
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Update content height when content changes
|
||||
useEffect(() => {
|
||||
if (contentRef.current) {
|
||||
setContentHeight(isOpen ? contentRef.current.scrollHeight : 0);
|
||||
if (isOpen && contentRef.current) {
|
||||
setContentHeight(contentRef.current.scrollHeight);
|
||||
}
|
||||
}, [isOpen]);
|
||||
}, [children, isOpen]); // Dependency on children and isOpen
|
||||
|
||||
const heightProps = useSpring({
|
||||
height: isOpen ? `${contentHeight}px` : "0px",
|
||||
@@ -89,24 +90,22 @@ function AccordionItem({
|
||||
}
|
||||
|
||||
function Accordion({ children }: AccordionProps) {
|
||||
const [openItems, setOpenItems] = useState<string[]>([]);
|
||||
// Extract titles of items that should be initially open
|
||||
const defaultOpenTitles = React.Children.toArray(children)
|
||||
.filter((child: any) => child.props.defaultOpen)
|
||||
.map((child: any) => child.props.title);
|
||||
|
||||
// Initialize openItems with the titles of items that should be open
|
||||
const [openItems, setOpenItems] = useState<string[]>(defaultOpenTitles);
|
||||
|
||||
const toggleItem = (title: string) => {
|
||||
if (openItems.includes(title)) {
|
||||
setOpenItems(openItems.filter((item) => item !== title));
|
||||
setOpenItems(openItems.filter(item => item !== title));
|
||||
} else {
|
||||
setOpenItems([...openItems, title]);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize openItems based on defaultOpen props of AccordionItem children
|
||||
useEffect(() => {
|
||||
const defaultOpenItems = React.Children.toArray(children)
|
||||
.filter((child: any) => child.props.defaultOpen)
|
||||
.map((child: any) => child.props.title);
|
||||
setOpenItems(defaultOpenItems);
|
||||
}, [children]);
|
||||
|
||||
return (
|
||||
<AccordionContext.Provider value={{ openItems, toggleItem }}>
|
||||
<div className="d-flex flex-column gap-3">{children}</div>
|
||||
|
||||
@@ -34,6 +34,7 @@ import LikeButton from "components/common/LikeButton";
|
||||
import NonRouteTabs from "components/common/Tabs/NonRouteTabs";
|
||||
import { SessionVoiceConversionResultsList } from "v2/view/_common/SessionVoiceConversionResultsList";
|
||||
import SplitPanel from "components/common/SplitPanel";
|
||||
import VdInferencePanel from "./inference_panels/VdInferencePanel";
|
||||
// import PitchEstimateMethodComponent from "../vc/vc_model_list/components/PitchEstimateMethodComponent";
|
||||
// import PitchShiftComponent from "../vc/vc_model_list/components/PitchShiftComponent";
|
||||
// import { SessionVoiceConversionResultsList } from "v2/view/_common/SessionVoiceConversionResultsList";
|
||||
@@ -73,8 +74,8 @@ export default function WeightsPage({
|
||||
title: "Harry Potter (Daniel Radcliffe)",
|
||||
created_at: new Date(),
|
||||
updated_at: new Date(),
|
||||
weight_type: WeightType.TT2,
|
||||
weight_category: WeightCategory.VC,
|
||||
weight_type: WeightType.VALL_E,
|
||||
weight_category: WeightCategory.ZS,
|
||||
maybe_creator_user: {
|
||||
user_token: "test",
|
||||
username: "test",
|
||||
@@ -112,7 +113,7 @@ export default function WeightsPage({
|
||||
<Panel padding={true}>
|
||||
<form className="mb-4">
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<h4 className="fw-semibold">Use Voice</h4>
|
||||
<h4 className="fw-semibold">Generate TTS</h4>
|
||||
<TextArea
|
||||
placeholder="Enter the text you want your character to say here..."
|
||||
// value={textBuffer}
|
||||
@@ -330,7 +331,7 @@ export default function WeightsPage({
|
||||
return (
|
||||
<SplitPanel>
|
||||
<SplitPanel.Header padding={true}>
|
||||
<h4 className="fw-semibold mb-0">Use Voice</h4>
|
||||
<h4 className="fw-semibold mb-0">Generate Voice Conversion</h4>
|
||||
</SplitPanel.Header>
|
||||
|
||||
<SplitPanel.Body>
|
||||
@@ -343,7 +344,7 @@ export default function WeightsPage({
|
||||
</SplitPanel.Body>
|
||||
<SplitPanel.Footer padding={true}>
|
||||
<Accordion>
|
||||
<Accordion.Item title="Session VC Results" defaultOpen={false}>
|
||||
<Accordion.Item title="Session V2V Results" defaultOpen={false}>
|
||||
<SessionVoiceConversionResultsList
|
||||
inferenceJobs={
|
||||
inferenceJobsByCategory.get(
|
||||
@@ -360,54 +361,19 @@ export default function WeightsPage({
|
||||
|
||||
case WeightCategory.ZS:
|
||||
return (
|
||||
//Since zero-shot has only tts for now, we can use the same thing as TTS
|
||||
<Panel padding={true}>
|
||||
<form className="mb-4">
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<h4 className="fw-semibold">Use Voice</h4>
|
||||
<TextArea
|
||||
placeholder="Enter the text you want your character to say here..."
|
||||
// value={textBuffer}
|
||||
// onChange={handleChangeText}
|
||||
rows={6}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="d-flex gap-2 justify-content-end mt-3">
|
||||
<Button
|
||||
icon={faDeleteLeft}
|
||||
label="Clear"
|
||||
variant="danger"
|
||||
// onClick={handleClearText}
|
||||
/>
|
||||
<Button
|
||||
icon={faVolumeUp}
|
||||
label="Speak"
|
||||
// onClick={handleEnqueueTts}
|
||||
// isLoading={isEnqueuing}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<Accordion>
|
||||
<Accordion.Item title="Session TTS Results" defaultOpen={false}>
|
||||
<div>
|
||||
<SessionVoiceDesignerInferenceResultsList
|
||||
inferenceJobs={
|
||||
inferenceJobsByCategory.get(
|
||||
FrontendInferenceJobType.VoiceDesignerTts
|
||||
)!
|
||||
}
|
||||
ttsInferenceJobs={ttsInferenceJobs}
|
||||
sessionSubscriptionsWrapper={sessionSubscriptionsWrapper}
|
||||
/>
|
||||
</div>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</Panel>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<VdInferencePanel
|
||||
inferenceJobs={inferenceJobs}
|
||||
sessionSubscriptionsWrapper={sessionSubscriptionsWrapper}
|
||||
enqueueInferenceJob={enqueueInferenceJob}
|
||||
inferenceJobsByCategory={inferenceJobsByCategory}
|
||||
ttsInferenceJobs={ttsInferenceJobs}
|
||||
voiceToken={weight.weight_token}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return "No weight component found";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,7 +492,7 @@ export default function WeightsPage({
|
||||
weightCategory: "",
|
||||
};
|
||||
|
||||
const ttsDetails = [
|
||||
const voiceDetails = [
|
||||
{ property: "Type", value: weightType },
|
||||
{ property: "Category", value: weightCategory },
|
||||
{
|
||||
@@ -537,32 +503,30 @@ export default function WeightsPage({
|
||||
{ property: "Updated at", value: weight.updated_at.toString() },
|
||||
];
|
||||
|
||||
const vcDetails = [
|
||||
{ property: "Type", value: weight.weight_type },
|
||||
{ property: "Created at", value: weight.created_at.toString() },
|
||||
{
|
||||
property: "Visibility",
|
||||
value: weight.creator_set_visibility.toString(),
|
||||
},
|
||||
];
|
||||
|
||||
const imageDetails = [
|
||||
{ property: "Type", value: weight.weight_type },
|
||||
{ property: "Created at", value: weight.created_at.toString() },
|
||||
{ property: "Type", value: weightType },
|
||||
{ property: "Category", value: weightCategory },
|
||||
{
|
||||
property: "Visibility",
|
||||
value: weight.creator_set_visibility.toString(),
|
||||
},
|
||||
{ property: "Created at", value: weight.created_at.toString() },
|
||||
{ property: "Updated at", value: weight.updated_at.toString() },
|
||||
|
||||
//more to add for image/stable diffusion details
|
||||
];
|
||||
|
||||
let weightDetails = undefined;
|
||||
|
||||
switch (weight.weight_category) {
|
||||
case WeightCategory.TTS:
|
||||
weightDetails = <DataTable data={ttsDetails} />;
|
||||
weightDetails = <DataTable data={voiceDetails} />;
|
||||
break;
|
||||
case WeightCategory.VC:
|
||||
weightDetails = <DataTable data={vcDetails} />;
|
||||
weightDetails = <DataTable data={voiceDetails} />;
|
||||
break;
|
||||
case WeightCategory.ZS:
|
||||
weightDetails = <DataTable data={voiceDetails} />;
|
||||
break;
|
||||
case WeightCategory.SD:
|
||||
weightDetails = <DataTable data={imageDetails} />;
|
||||
@@ -572,6 +536,7 @@ export default function WeightsPage({
|
||||
|
||||
let modMediaDetails = undefined;
|
||||
|
||||
//dummy content
|
||||
const modDetails = [
|
||||
{ property: "Model creator is banned", value: "good standing" },
|
||||
{
|
||||
@@ -634,7 +599,7 @@ export default function WeightsPage({
|
||||
<div>
|
||||
<Badge label={weightType} color={weightTagColor} />
|
||||
</div>
|
||||
<p>Text to Speech</p>
|
||||
<p>{weightCategory}</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -644,10 +609,12 @@ export default function WeightsPage({
|
||||
<div className="col-12 col-xl-8 d-flex flex-column gap-3">
|
||||
<div className="media-wrapper">{renderWeightComponent(weight)}</div>
|
||||
|
||||
<Panel padding={true}>
|
||||
<h4 className="fw-semibold mb-3">Description</h4>
|
||||
<p>{weight.description_markdown}</p>
|
||||
</Panel>
|
||||
{weight.description_markdown !== "" && (
|
||||
<Panel padding={true}>
|
||||
<h4 className="fw-semibold mb-3">Description</h4>
|
||||
<p>{weight.description_markdown}</p>
|
||||
</Panel>
|
||||
)}
|
||||
|
||||
<div className="panel p-3 py-4 p-md-4 d-none d-xl-block">
|
||||
<h4 className="fw-semibold mb-3">Comments</h4>
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import React, { useState } from "react";
|
||||
import { faDeleteLeft } from "@fortawesome/pro-solid-svg-icons";
|
||||
import Panel from "components/common/Panel/Panel";
|
||||
import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper";
|
||||
import TextArea from "components/common/TextArea";
|
||||
import { Button } from "components/common";
|
||||
import {
|
||||
FrontendInferenceJobType,
|
||||
InferenceJob,
|
||||
} from "@storyteller/components/src/jobs/InferenceJob";
|
||||
import { TtsInferenceJob } from "@storyteller/components/src/jobs/TtsInferenceJobs";
|
||||
import { faVolumeUp } from "@fortawesome/free-solid-svg-icons";
|
||||
import useVoiceRequests from "../../voice_designer/useVoiceRequests";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import Accordion from "components/common/Accordion";
|
||||
import { SessionVoiceDesignerInferenceResultsList } from "v2/view/_common/SessionVoiceDesignerInferenceResultsList";
|
||||
|
||||
interface VdInferencePanelProps {
|
||||
sessionSubscriptionsWrapper: SessionSubscriptionsWrapper;
|
||||
inferenceJobs: Array<InferenceJob>;
|
||||
ttsInferenceJobs: Array<TtsInferenceJob>;
|
||||
enqueueInferenceJob: (
|
||||
jobToken: string,
|
||||
frontendInferenceJobType: FrontendInferenceJobType
|
||||
) => void;
|
||||
inferenceJobsByCategory: Map<FrontendInferenceJobType, Array<InferenceJob>>;
|
||||
voiceToken: string;
|
||||
}
|
||||
|
||||
export default function VdInferencePanel({
|
||||
inferenceJobs,
|
||||
sessionSubscriptionsWrapper,
|
||||
ttsInferenceJobs,
|
||||
enqueueInferenceJob,
|
||||
inferenceJobsByCategory,
|
||||
voiceToken,
|
||||
}: VdInferencePanelProps) {
|
||||
const [textBuffer, setTextBuffer] = useState("");
|
||||
const { inference } = useVoiceRequests({});
|
||||
const [isEnqueuing, setIsEnqueuing] = useState(false);
|
||||
|
||||
const handleEnqueueTts = () => {
|
||||
setIsEnqueuing(true);
|
||||
inference
|
||||
.enqueue("", {
|
||||
uuid_idempotency_token: uuidv4(),
|
||||
text: textBuffer,
|
||||
voice_token: voiceToken,
|
||||
})
|
||||
.then((res: any) => {
|
||||
if (res && res.success) {
|
||||
enqueueInferenceJob(
|
||||
res.inference_job_token,
|
||||
FrontendInferenceJobType.VoiceDesignerTts
|
||||
);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error enqueuing TTS:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
setIsEnqueuing(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleChangeText = (ev: React.FormEvent<HTMLTextAreaElement>) => {
|
||||
const textValue = (ev.target as HTMLTextAreaElement).value;
|
||||
setTextBuffer(textValue);
|
||||
};
|
||||
|
||||
const handleClearText = () => {
|
||||
setTextBuffer("");
|
||||
};
|
||||
|
||||
return (
|
||||
<Panel padding={true}>
|
||||
<form>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<h4 className="fw-semibold">Generate TTS</h4>
|
||||
<TextArea
|
||||
placeholder="Enter the text you want your character to say here..."
|
||||
value={textBuffer}
|
||||
onChange={handleChangeText}
|
||||
rows={6}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="d-flex gap-2 justify-content-end mt-3">
|
||||
<Button
|
||||
icon={faDeleteLeft}
|
||||
label="Clear"
|
||||
variant="danger"
|
||||
onClick={handleClearText}
|
||||
disabled={textBuffer.length === 0}
|
||||
/>
|
||||
<Button
|
||||
icon={faVolumeUp}
|
||||
label="Speak"
|
||||
onClick={handleEnqueueTts}
|
||||
isLoading={isEnqueuing}
|
||||
disabled={textBuffer.length === 0}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{inferenceJobs[0] && (
|
||||
<div className="mt-4">
|
||||
<Accordion>
|
||||
<Accordion.Item title="Session TTS Results" defaultOpen={true}>
|
||||
<div className="p-3">
|
||||
<SessionVoiceDesignerInferenceResultsList
|
||||
inferenceJobs={
|
||||
inferenceJobsByCategory.get(
|
||||
FrontendInferenceJobType.VoiceDesignerTts
|
||||
)!
|
||||
}
|
||||
ttsInferenceJobs={ttsInferenceJobs}
|
||||
sessionSubscriptionsWrapper={sessionSubscriptionsWrapper}
|
||||
/>
|
||||
</div>
|
||||
</Accordion.Item>
|
||||
</Accordion>
|
||||
</div>
|
||||
)}
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user