mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 17:58:55 +00:00
require users to login for voice designer
This commit is contained in:
1 parent
8894ea82c8
commit
993dc9c00f
6 files changed
+241
-58
No files matched your search
@@ -644,7 +644,10 @@ class PageContainer extends React.Component<
|
||||
path="/voice-designer/create"
|
||||
>
|
||||
<VoiceDesignerFormPage {...{
|
||||
enqueueInferenceJob: this.props.enqueueInferenceJob
|
||||
enqueueInferenceJob: this.props.enqueueInferenceJob,
|
||||
sessionWrapper: this.props.sessionWrapper,
|
||||
sessionSubscriptionsWrapper:
|
||||
this.props.sessionSubscriptionsWrapper
|
||||
}}/>
|
||||
</Route>
|
||||
|
||||
@@ -654,7 +657,10 @@ class PageContainer extends React.Component<
|
||||
path="/voice-designer/dataset/:dataset_token/edit"
|
||||
>
|
||||
<VoiceDesignerFormPage {...{
|
||||
enqueueInferenceJob: this.props.enqueueInferenceJob
|
||||
enqueueInferenceJob: this.props.enqueueInferenceJob,
|
||||
sessionWrapper: this.props.sessionWrapper,
|
||||
sessionSubscriptionsWrapper:
|
||||
this.props.sessionSubscriptionsWrapper
|
||||
}}/>
|
||||
</Route>
|
||||
|
||||
@@ -664,7 +670,10 @@ class PageContainer extends React.Component<
|
||||
path="/voice-designer/dataset/:dataset_token/upload"
|
||||
>
|
||||
<VoiceDesignerFormPage {...{
|
||||
enqueueInferenceJob: this.props.enqueueInferenceJob
|
||||
enqueueInferenceJob: this.props.enqueueInferenceJob,
|
||||
sessionWrapper: this.props.sessionWrapper,
|
||||
sessionSubscriptionsWrapper:
|
||||
this.props.sessionSubscriptionsWrapper
|
||||
}}/>
|
||||
</Route>
|
||||
|
||||
@@ -687,6 +696,9 @@ class PageContainer extends React.Component<
|
||||
|
||||
<Route path="/voice-designer">
|
||||
<VoiceDesignerMainPage {...{
|
||||
sessionWrapper:this.props.sessionWrapper,
|
||||
sessionSubscriptionsWrapper:
|
||||
this.props.sessionSubscriptionsWrapper,
|
||||
enqueueInferenceJob: this.props.enqueueInferenceJob,
|
||||
inferenceJobs: this.props.inferenceJobs,
|
||||
inferenceJobsByCategory: this.props.inferenceJobsByCategory
|
||||
|
||||
@@ -24,12 +24,13 @@ import useVoiceRequests from "./useVoiceRequests";
|
||||
import useUploadedFiles from "hooks/useUploadedFiles";
|
||||
|
||||
import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob";
|
||||
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
|
||||
|
||||
interface RouteParams {
|
||||
dataset_token?: string;
|
||||
}
|
||||
|
||||
function VoiceDesignerFormPage({ enqueueInferenceJob }: { enqueueInferenceJob: any }) {
|
||||
function VoiceDesignerFormPage({ enqueueInferenceJob, sessionWrapper }: { enqueueInferenceJob: any, sessionWrapper: SessionWrapper }) {
|
||||
const history = useHistory();
|
||||
const { datasets, inputCtrl, languages, visibilityOptions, voices } = useVoiceRequests({});
|
||||
const [language, languageSet] = useState("en");
|
||||
@@ -168,6 +169,10 @@ function VoiceDesignerFormPage({ enqueueInferenceJob }: { enqueueInferenceJob: a
|
||||
}
|
||||
},[dataset_token,datasets,fetched]);
|
||||
|
||||
if (!sessionWrapper.isLoggedIn()) {
|
||||
history.push("/voice-designer");
|
||||
}
|
||||
|
||||
return (
|
||||
<Container type="panel">
|
||||
<PageHeader
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState } from "react";
|
||||
import { Redirect, useHistory, useLocation } from "react-router-dom";
|
||||
import { faPlus, faWaveform } from "@fortawesome/pro-solid-svg-icons";
|
||||
import InferenceJobsList from "components/layout/InferenceJobsList";
|
||||
import { useLocalize } from "hooks";
|
||||
import { useLocalize, useSession } from "hooks";
|
||||
import Panel from "components/common/Panel";
|
||||
import PageHeader from "components/layout/PageHeader";
|
||||
import Container from "components/common/Container";
|
||||
@@ -16,12 +16,17 @@ import {
|
||||
FrontendInferenceJobType,
|
||||
// InferenceJob,
|
||||
} from "@storyteller/components/src/jobs/InferenceJob";
|
||||
import { VdPageHero } from "./components/VdPageHero";
|
||||
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
|
||||
import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper";
|
||||
|
||||
function VoiceDesignerMainPage({
|
||||
inferenceJobsByCategory,
|
||||
}: {
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper;
|
||||
sessionSubscriptionsWrapper: SessionSubscriptionsWrapper;
|
||||
inferenceJobsByCategory: any;
|
||||
}) {
|
||||
}
|
||||
|
||||
function VoiceDesignerMainPage(props: Props) {
|
||||
usePrefixedDocumentTitle("AI Voice Designer");
|
||||
const { pathname } = useLocation();
|
||||
const { t } = useLocalize("FaceAnimator");
|
||||
@@ -40,6 +45,7 @@ function VoiceDesignerMainPage({
|
||||
text: "",
|
||||
});
|
||||
|
||||
|
||||
const history = useHistory();
|
||||
|
||||
if (pathname === "/voice-designer" || pathname === "/voice-designer/") {
|
||||
@@ -157,59 +163,109 @@ function VoiceDesignerMainPage({
|
||||
to: "/voice-designer/create",
|
||||
};
|
||||
|
||||
const isLoggedIn = props.sessionWrapper.isLoggedIn();
|
||||
let pageHeader = <></>;
|
||||
if (!isLoggedIn) {
|
||||
pageHeader = (
|
||||
<VdPageHero
|
||||
sessionWrapper={props.sessionWrapper}
|
||||
/>)
|
||||
} else {
|
||||
pageHeader = (
|
||||
<PageHeader
|
||||
button={button}
|
||||
title="Voice Designer"
|
||||
titleIcon={faWaveform}
|
||||
subText="Create your own AI voice by providing audio files of the voice you want to clone."
|
||||
panel={false}
|
||||
imageUrl="/images/header/voice-designer.png"
|
||||
/>)
|
||||
}
|
||||
|
||||
let body = <></>;
|
||||
|
||||
if (!isLoggedIn) {
|
||||
body = (
|
||||
<div className="container section mb-3 d-flex flex-column align-items-center">
|
||||
<div className="d-flex justify-content-center align-items-center gap-4">
|
||||
<img className="rotateimg180" src="assets/title-shape.png" alt="" />
|
||||
<img src="assets/title-shape.png" alt="" />
|
||||
</div>
|
||||
{/* <h1 className=" fw-bold mb-4 mt-3">
|
||||
<span className="word">Join Our Community</span>
|
||||
</h1> */}
|
||||
<p className="lead text-center mb-5">
|
||||
This feature requires a subscription
|
||||
<br />
|
||||
Log in or Sign Up!
|
||||
<br />
|
||||
Also join us on Discord so that we know what you're thinking.
|
||||
</p>
|
||||
<div className="d-flex flex-column flex-lg-row gap-3 mb-5">
|
||||
<button className="btn btn-secondary">
|
||||
<i className="fa-brands fa-twitter me-2"></i>Follow on Twitter
|
||||
</button>
|
||||
<button className="btn btn-primary">
|
||||
<i className="fa-brands fa-discord me-2"></i>Join our Discord
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
body = (
|
||||
<>
|
||||
<InferenceJobsList
|
||||
{...{
|
||||
t,
|
||||
inferenceJobs: props.inferenceJobsByCategory.get(
|
||||
FrontendInferenceJobType.VoiceDesignerCreateVoice
|
||||
),
|
||||
statusTxt,
|
||||
}}
|
||||
/>
|
||||
<Panel mb={true}>
|
||||
<nav>
|
||||
<ul className="nav nav-tabs">
|
||||
<div className="d-flex flex-grow-1">
|
||||
<li className="nav-item">
|
||||
<NavLink
|
||||
to="/voice-designer/voices"
|
||||
className="nav-link fs-6 px-3 px-lg-4"
|
||||
activeClassName="active"
|
||||
>
|
||||
My Voices
|
||||
</NavLink>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<NavLink
|
||||
to="/voice-designer/datasets"
|
||||
className="nav-link fs-6"
|
||||
activeClassName="active"
|
||||
>
|
||||
My Datasets
|
||||
</NavLink>
|
||||
</li>
|
||||
</div>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div className="p-3 p-lg-4">
|
||||
<ListItems
|
||||
{...{ data: view ? actionVoices : actionDataSets }}
|
||||
isLoading={isFetching}
|
||||
/>
|
||||
</div>
|
||||
</Panel>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Container type="panel">
|
||||
<PageHeader
|
||||
button={button}
|
||||
title="Voice Designer"
|
||||
titleIcon={faWaveform}
|
||||
subText="Create your own AI voice by providing audio files of the voice you want to clone."
|
||||
panel={false}
|
||||
imageUrl="/images/header/voice-designer.png"
|
||||
/>
|
||||
<InferenceJobsList
|
||||
{...{
|
||||
t,
|
||||
inferenceJobs: inferenceJobsByCategory.get(
|
||||
FrontendInferenceJobType.VoiceDesignerCreateVoice
|
||||
),
|
||||
statusTxt,
|
||||
}}
|
||||
/>
|
||||
<Panel mb={true}>
|
||||
<nav>
|
||||
<ul className="nav nav-tabs">
|
||||
<div className="d-flex flex-grow-1">
|
||||
<li className="nav-item">
|
||||
<NavLink
|
||||
to="/voice-designer/voices"
|
||||
className="nav-link fs-6 px-3 px-lg-4"
|
||||
activeClassName="active"
|
||||
>
|
||||
My Voices
|
||||
</NavLink>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<NavLink
|
||||
to="/voice-designer/datasets"
|
||||
className="nav-link fs-6"
|
||||
activeClassName="active"
|
||||
>
|
||||
My Datasets
|
||||
</NavLink>
|
||||
</li>
|
||||
</div>
|
||||
</ul>
|
||||
</nav>
|
||||
{pageHeader}
|
||||
|
||||
<div className="p-3 p-lg-4">
|
||||
<ListItems
|
||||
{...{ data: view ? actionVoices : actionDataSets }}
|
||||
isLoading={isFetching}
|
||||
/>
|
||||
</div>
|
||||
</Panel>
|
||||
{body}
|
||||
</Container>
|
||||
|
||||
{/* Delete Modal */}
|
||||
|
||||
@@ -31,6 +31,7 @@ import { GetVoice } from "@storyteller/components/src/api/voice_designer/voices/
|
||||
import Skeleton from "components/common/Skeleton";
|
||||
import useVoiceRequests from "./useVoiceRequests";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
interface VoiceDesignerUseVoicePageProps {
|
||||
sessionWrapper: SessionWrapper;
|
||||
@@ -62,6 +63,7 @@ export default function VoiceDesignerUseVoicePage(
|
||||
});
|
||||
const { inference } = useVoiceRequests({});
|
||||
const [isEnqueuing, setIsEnqueuing] = useState(false);
|
||||
const history = useHistory();
|
||||
|
||||
const getVoiceDetails = useCallback(async (voice_token) => {
|
||||
try {
|
||||
@@ -189,6 +191,10 @@ export default function VoiceDesignerUseVoicePage(
|
||||
);
|
||||
}
|
||||
|
||||
if (!props.sessionWrapper.isLoggedIn()) {
|
||||
history.push("/voice-designer");
|
||||
}
|
||||
|
||||
return (
|
||||
<Container type="panel">
|
||||
<PageHeader title={voiceData.title} subText={subText} />
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
import React, { useMemo } from "react";
|
||||
import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper";
|
||||
import { Link } from "react-router-dom";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
faStar,
|
||||
faUser,
|
||||
faArrowRight,
|
||||
faMicrophoneStand,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
|
||||
import { useLocalize } from "hooks";
|
||||
import { PageHeaderWithImage } from "v2/view/_common/PageHeaderWithImage";
|
||||
import { WebUrl } from "common/WebUrl";
|
||||
import { Analytics } from "common/Analytics";
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper;
|
||||
}
|
||||
|
||||
export function VdPageHero(props: Props) {
|
||||
const { t } = useLocalize("VcModelListPage");
|
||||
const randomImage = useMemo(() => {
|
||||
const images = ["/images/header/voice-designer.png"];
|
||||
|
||||
return images[Math.floor(Math.random() * images.length)];
|
||||
}, []);
|
||||
|
||||
let signUpButton = <></>;
|
||||
let viewPricingButton = <></>;
|
||||
let loginButton = <></>;
|
||||
const loggedIn = props.sessionWrapper.isLoggedIn();
|
||||
|
||||
if (!loggedIn) {
|
||||
signUpButton = (
|
||||
<>
|
||||
<Link
|
||||
to="/signup"
|
||||
onClick={() => {
|
||||
Analytics.ttsClickHeroSignup();
|
||||
}}
|
||||
>
|
||||
<button type="button" className="btn btn-primary w-100">
|
||||
{t("heroButtonSignUp")}
|
||||
<FontAwesomeIcon icon={faArrowRight} className="ms-2" />
|
||||
</button>
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
viewPricingButton = (
|
||||
<>
|
||||
<Link
|
||||
to={WebUrl.pricingPageWithReferer("tts_hero_new")}
|
||||
onClick={() => {
|
||||
Analytics.ttsClickHeroViewPricing();
|
||||
}}
|
||||
>
|
||||
<button type="button" className="btn btn-secondary w-100">
|
||||
<FontAwesomeIcon icon={faStar} className="me-2" />
|
||||
{t("heroButtonPricing")}
|
||||
</button>
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
|
||||
loginButton = (
|
||||
<>
|
||||
<Link to={WebUrl.loginPage()}>
|
||||
<button type="button" className="btn btn-secondary w-100">
|
||||
<FontAwesomeIcon icon={faMicrophoneStand} className="me-2" />
|
||||
{ "Login" }
|
||||
</button>
|
||||
</Link>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const titleIcon = (
|
||||
<FontAwesomeIcon icon={faMicrophoneStand} className="me-3 me-lg-4" />
|
||||
);
|
||||
const title = <>{"Voice Designer"}</>;
|
||||
const subText = <>{t("heroText")}</>;
|
||||
const actionButtons = (
|
||||
<>
|
||||
{signUpButton}
|
||||
{loginButton}
|
||||
{viewPricingButton}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeaderWithImage
|
||||
headerImage={randomImage}
|
||||
titleIcon={titleIcon}
|
||||
title={title}
|
||||
subText={subText}
|
||||
showButtons={true}
|
||||
actionButtons={actionButtons}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
+1
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
import VoiceDesignerUploadComponent from "../VoiceDesignerUploadComponent";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { SessionContext } from 'context';
|
||||
|
||||
function UploadSamples({ audioProps, datasetToken, setAudioSamplesReady }: { audioProps: any, datasetToken?: string, setAudioSamplesReady:any }) {
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
|
||||
Reference in new issue
Block a user