mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 01:18:34 +00:00
greatly improved
This commit is contained in:
1 parent
f4193046e5
commit
faa75eae82
5 files changed
+167
-24
No files matched your search
@@ -2,12 +2,13 @@ import 'bulma/css/bulma.css'
|
||||
import './App.css';
|
||||
|
||||
import React from 'react';
|
||||
import { ComponentFrame, ShowComponent } from './components/ComponentFrame';
|
||||
import { ShowComponent } from './components/ComponentFrame';
|
||||
import ApiConfig from './api/ApiConfig';
|
||||
import ModeButtons from './components/ModeButtons';
|
||||
import { SpeakerDetails } from './api/ApiDefinition';
|
||||
import { Form } from './components/Form';
|
||||
import { Speaker } from './model/Speaker';
|
||||
import { Utterance } from './model/Utterance';
|
||||
import { UtteranceHistory } from './components/UtteranceHistory';
|
||||
|
||||
interface Props {
|
||||
}
|
||||
@@ -18,6 +19,7 @@ interface State {
|
||||
speakers: Speaker[],
|
||||
currentText: string,
|
||||
currentSpeaker?: Speaker;
|
||||
pastUtterances: Utterance[],
|
||||
}
|
||||
|
||||
class App extends React.Component<Props, State> {
|
||||
@@ -29,6 +31,7 @@ class App extends React.Component<Props, State> {
|
||||
apiConfig: new ApiConfig(),
|
||||
speakers: [],
|
||||
currentText: "",
|
||||
pastUtterances: [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,7 +40,7 @@ class App extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
public loadSpeakers() {
|
||||
const url = this.state.apiConfig.getEndpoint('/speakers');
|
||||
const url = this.state.apiConfig.getEndpoint('/voices');
|
||||
|
||||
fetch(url)
|
||||
.then(res => res.json())
|
||||
@@ -84,6 +87,13 @@ class App extends React.Component<Props, State> {
|
||||
});
|
||||
}
|
||||
|
||||
addUtterance = (utterance: Utterance) => {
|
||||
let utterances = this.state.pastUtterances.concat(utterance);
|
||||
this.setState({
|
||||
pastUtterances: utterances,
|
||||
})
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div>
|
||||
@@ -98,11 +108,12 @@ class App extends React.Component<Props, State> {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/*
|
||||
=== TODO ===
|
||||
<ModeButtons
|
||||
showComponent={this.state.showComponent}
|
||||
switchShowComponentCallback={this.switchComponent}
|
||||
/>
|
||||
|
||||
<hr />
|
||||
|
||||
<ComponentFrame
|
||||
@@ -112,13 +123,27 @@ class App extends React.Component<Props, State> {
|
||||
currentSpeaker={this.state.currentSpeaker}
|
||||
updateTextCallback={this.updateText}
|
||||
/>
|
||||
*/}
|
||||
<Form
|
||||
apiConfig={this.state.apiConfig}
|
||||
speakers={this.state.speakers}
|
||||
currentSpeaker={this.state.currentSpeaker}
|
||||
currentText={this.state.currentText}
|
||||
changeSpeakerBySlug={this.updateSpeakerBySlug}
|
||||
changeText={this.updateText}
|
||||
addUtteranceCallback={this.addUtterance}
|
||||
/>
|
||||
<section className="section is-small">
|
||||
<h1 className="title">Results</h1>
|
||||
<h2 className="subtitle">
|
||||
Your results will go here.
|
||||
Please make make lots of YouTube videos before anyone else has access!
|
||||
</h2>
|
||||
</section>
|
||||
|
||||
<UtteranceHistory
|
||||
utterances={this.state.pastUtterances}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
import React from 'react';
|
||||
import Howl from 'howler';
|
||||
import { Speaker } from '../model/Speaker';
|
||||
import { SpeakRequest } from '../api/ApiDefinition';
|
||||
import ApiConfig from '../api/ApiConfig';
|
||||
import { Utterance } from '../model/Utterance';
|
||||
|
||||
interface Props {
|
||||
currentText: string,
|
||||
currentSpeaker?: Speaker,
|
||||
speakers: Speaker[],
|
||||
apiConfig: ApiConfig,
|
||||
changeSpeakerBySlug: (speakerSlug: string) => void,
|
||||
changeText: (text: string) => void,
|
||||
addUtteranceCallback: (utterance: Utterance) => void,
|
||||
}
|
||||
|
||||
interface State {
|
||||
@@ -30,6 +36,57 @@ class Form extends React.Component<Props, State> {
|
||||
this.props.changeText(value);
|
||||
}
|
||||
|
||||
makeRequest = (ev: React.FormEvent<HTMLFormElement>) => {
|
||||
const that = this;
|
||||
console.log("Form Submit");
|
||||
|
||||
if (!this.props.currentText) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.props.currentSpeaker === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const speaker = this.props.currentSpeaker;
|
||||
const text = this.props.currentText;
|
||||
|
||||
let request = new SpeakRequest(text, speaker!.slug);
|
||||
|
||||
const url = this.props.apiConfig.getEndpoint('/speak');
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(request),
|
||||
})
|
||||
.then(res => res.blob())
|
||||
.then(blob => {
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
||||
console.log('download at the audio url:');
|
||||
console.log(url);
|
||||
|
||||
const sound = new Howl.Howl({
|
||||
src: [url],
|
||||
format: ['wav'],
|
||||
});
|
||||
|
||||
this.setState({howl: sound});
|
||||
sound.play();
|
||||
|
||||
const utterance = new Utterance(speaker, text, url, sound);
|
||||
that.props.addUtteranceCallback(utterance);
|
||||
});
|
||||
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public render() {
|
||||
let speakerOptions : any = [];
|
||||
|
||||
@@ -39,27 +96,31 @@ class Form extends React.Component<Props, State> {
|
||||
|
||||
return (
|
||||
<div className="box">
|
||||
<div className="field">
|
||||
<label className="label">Speaker</label>
|
||||
<div className="control">
|
||||
<div className="select">
|
||||
<select onChange={this.changeSpeaker}>
|
||||
{speakerOptions}
|
||||
</select>
|
||||
<form onSubmit={this.makeRequest}>
|
||||
<div className="field">
|
||||
<label className="label">Speaker</label>
|
||||
<div className="control">
|
||||
<div className="select">
|
||||
<select onChange={this.changeSpeaker}>
|
||||
{speakerOptions}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label className="label">Text</label>
|
||||
<div className="control">
|
||||
<input
|
||||
onChange={this.changeText}
|
||||
className="input is-large"
|
||||
type="text"
|
||||
placeholder="TTS"
|
||||
/>
|
||||
<div className="field">
|
||||
<label className="label">Text</label>
|
||||
<div className="control">
|
||||
<input
|
||||
onChange={this.changeText}
|
||||
className="input is-large"
|
||||
type="text"
|
||||
placeholder="TTS"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button className="button is-primary is-large">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import React from 'react';
|
||||
import { Utterance } from '../model/Utterance';
|
||||
|
||||
interface Props {
|
||||
utterances: Utterance[],
|
||||
}
|
||||
|
||||
interface State {
|
||||
}
|
||||
|
||||
class UtteranceHistory extends React.Component<Props, State> {
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
};
|
||||
}
|
||||
|
||||
public render() {
|
||||
let utterances = this.props.utterances.map(utterance => {
|
||||
return (
|
||||
<div className="box">
|
||||
<article className="media">
|
||||
<div className="media-content">
|
||||
<div className="content">
|
||||
<p>
|
||||
<strong>{utterance.speaker.name}</strong> <small>{utterance.speaker.slug}</small>
|
||||
<br />
|
||||
{utterance.text}
|
||||
</p>
|
||||
<p>
|
||||
<a href="#" onClick={() => utterance.howl.play()}>Play</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href={utterance.url} target="_blank" download="vocodes-early-access.wav">Download</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
)
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
{utterances}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { UtteranceHistory };
|
||||
@@ -1,12 +1,17 @@
|
||||
import { Speaker } from "./Speaker";
|
||||
import Howl from 'howler';
|
||||
|
||||
class Utterance {
|
||||
speaker: Speaker
|
||||
text: string
|
||||
url: string
|
||||
howl: Howl.Howl
|
||||
|
||||
constructor(speaker: Speaker, text: string) {
|
||||
constructor(speaker: Speaker, text: string, url: string, howl: Howl.Howl) {
|
||||
this.speaker = speaker;
|
||||
this.text = text;
|
||||
this.url = url;
|
||||
this.howl = howl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ pub async fn get_speakers(
|
||||
}))
|
||||
}
|
||||
|
||||
#[get("/early_access_speakers")]
|
||||
#[get("/voices")]
|
||||
pub async fn get_early_access_speakers(
|
||||
_request: HttpRequest,
|
||||
app_state: Data<Arc<AppState>>
|
||||
|
||||
Reference in new issue
Block a user