retrieving list of voices from server

This commit is contained in:
wil committed 2024-04-03 16:27:53 -04:00
1 parent a0d9637719
commit 59b03fc0b1
3 files changed
+131 -39

No files matched your search

+46 -36
View File
@@ -5,10 +5,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
interface ListDropdownProps {
list: {[key: string] : string}[];
listDisplayKey?: string;
onSelect: (val:string)=>void
}
export const ListSearchDropdown = ({
list, onSelect
list, listDisplayKey, onSelect
}:ListDropdownProps) => {
const [selected, setSelected] = useState(list[0])
const [query, setQuery] = useState('')
@@ -26,13 +27,17 @@ export const ListSearchDropdown = ({
useEffect(()=>{
onSelect(Object.values(selected)[0]);
}, [selected]);
return (
<Combobox value={selected} onChange={setSelected}>
<div className="relative mt-1">
<div className="relative w-full cursor-default overflow-hidden rounded-md text-left shadow-md sm:text-sm">
<div className="relative w-full cursor-default rounded-md text-left shadow-md sm:text-sm">
<Combobox.Input
className="w-full border-none py-2 pl-3 pr-10 text-sm leading-5 bg-brand-secondary text-white outline-none outline-offset-0 transition-all duration-150 ease-in-out focus:outline-brand-primary"
displayValue={(item: {[key: string] : string}) => Object.values(item)[0]}
className="w-full border-none rounded-md py-2 pl-3 pr-10 text-sm leading-5 bg-brand-secondary text-white outline-none outline-offset-0 transition-all duration-150 ease-in-out focus:outline-brand-primary"
displayValue={(item: {[key: string] : string}) => {
if(listDisplayKey) return item[listDisplayKey];
else return Object.values(item)[0]
}}
onChange={(event) => setQuery(event.target.value)}
/>
<Combobox.Button className="absolute inset-y-0 right-0 flex items-center pr-2">
@@ -52,38 +57,43 @@ export const ListSearchDropdown = ({
Nothing found.
</div>
) : (
filteredList.map((item, itemIdx) => (
<Combobox.Option
key={itemIdx}
className={({ active }) =>
`relative cursor-pointer select-none py-2 pl-10 pr-4 ${
active ? 'text-white' : 'text-gray-400'
}`
}
value={item}
>
{({ selected, active }) => (
<>
<span
className={`block truncate ${
selected ? 'font-medium' : 'font-normal'
}`}
>
{Object.values(item)[0]}
</span>
{selected ? (
<span
className={`absolute inset-y-0 left-0 flex items-center pl-3 ${
active ? 'text-white' : 'text-teal-600'
}`}
>
<FontAwesomeIcon icon={faCheck} aria-hidden="true"/>
</span>
) : null}
</>
)}
</Combobox.Option>
))
filteredList.map((item, itemIdx) => {
if(itemIdx <= 10)
return (
<Combobox.Option
key={itemIdx}
className={({ active }) =>
`relative cursor-pointer select-none py-2 pl-10 pr-4 ${
active ? 'text-white' : 'text-gray-400'
}`
}
value={item}
>
{({ selected, active }) => (
<>
<span
className={`block truncate ${
selected ? 'font-medium' : 'font-normal'
}`}
>
{!listDisplayKey && Object.values(item)[0]}
{listDisplayKey && item[listDisplayKey]}
</span>
{selected ? (
<span
className={`absolute inset-y-0 left-0 flex items-center pl-3 ${
active ? 'text-white' : 'text-teal-600'
}`}
>
<FontAwesomeIcon icon={faCheck} aria-hidden="true"/>
</span>
) : null}
</>
)}
</Combobox.Option>
);
return null;
})
)}
</Combobox.Options>
</Transition>
@@ -1,4 +1,4 @@
import { useContext, useState } from "react";
import { useCallback, useContext, useEffect, useState } from "react";
import { faVolume, faShuffle, faPlay } from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { AppUiContext } from "../../contexts/AppUiContext";
@@ -11,6 +11,7 @@ import {
TransitionDialogue,
Textarea
} from "~/components";
import { ListTtsModels, TtsModelListItem } from "./utilities";
const testdata = [
{ name: 'Wade Cooper' },
@@ -33,6 +34,28 @@ export const DialogueTTS = ()=>{
hasAudio:false
});
const [ttsModels, setTtsModels] = useState<Array<TtsModelListItem>>([]);
const listModels = useCallback(async () => {
const ttsModelsLoaded = ttsModels.length > 0;
if (ttsModelsLoaded) {
return; // Already queried.
}
const models = await ListTtsModels();
if (models) {
setTtsModels(models);
}
}, []);
useEffect(() => {
listModels();
}, [listModels]);
// useEffect(() => {
// console.log(ttsModels);
// }, [ttsModels]);
const handleClose = ()=> {
dispatchAppUiState({
type: APPUI_ACTION_TYPES.CLOSE_DIALOGUE_TTS
@@ -69,8 +92,12 @@ export const DialogueTTS = ()=>{
>
<div className="flex flex-col">
<Label className="mb-1">Select a Voice</Label>
<ListSearchDropdown list={testdata} onSelect={handleOnSelect}/>
{/* <ListSearchDropdown list={testdata} onSelect={handleOnSelect}/> */}
<ListSearchDropdown
list={ttsModels}
listDisplayKey="title"
onSelect={handleOnSelect}
/>
<div className="flex w-full justify-between mt-4">
<Label>What would you like to say?</Label>
<div className="flex gap-2 items-center">
@@ -0,0 +1,55 @@
// https://api.fakeyou.com/tts/list
interface TtsModelListResponsePayload {
success: boolean,
models: Array<TtsModelListItem>,
}
export interface UserRatings {
positive_count: number,
negative_count: number,
// Total count does not take into account "neutral" ratings.
total_count: number,
}
export interface TtsModelListItem {
model_token: string,
tts_model_type: string,
creator_user_token: string,
creator_username: string,
creator_display_name: string,
creator_gravatar_hash: string,
ietf_language_tag: string,
ietf_primary_language_subtag: string,
updatable_slug: string,
title: string,
is_front_page_featured: boolean,
is_twitch_featured: boolean,
user_ratings: UserRatings,
category_tokens: string[],
created_at: string,
updated_at: string,
}
export async function ListTtsModels() : Promise<Array<TtsModelListItem>| undefined> {
const endpoint = 'https://api.fakeyou.com/tts/list';
return await fetch(endpoint, {
method: 'GET',
headers: {
'Accept': 'application/json',
},
credentials: 'include',
})
.then(res => res.json())
.then(res => {
const response : TtsModelListResponsePayload = res;
if (!response.success) {
return;
}
return response?.models;
})
.catch(e => {
return undefined;
});
}