mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-03 17:08:13 +00:00
Add final modal (#270)
Co-authored-by: Christopher Oliphant <RALifeCoach@users.noreply.github.com>
This commit is contained in:
1 parent
6a1d7ee5f5
commit
4ac9ca4d77
17 files changed
+475
-138
No files matched your search
@@ -1,6 +1,5 @@
|
||||
import MakeRequest from "../MakeRequest";
|
||||
import { MediaFile } from "./GetMedia";
|
||||
import { Pagination } from "../_common/SharedFetchTypes";
|
||||
import { MediaFile, Pagination } from "~/pages/PageEnigma/models";
|
||||
|
||||
export interface GetMediaRequest {}
|
||||
|
||||
@@ -12,6 +11,7 @@ export interface GetMediaListResponse {
|
||||
|
||||
export interface GetMediaParams {
|
||||
page_index: number;
|
||||
filter_media_type: string;
|
||||
}
|
||||
|
||||
export const GetMediaByUser = MakeRequest<
|
||||
@@ -23,4 +23,4 @@ export const GetMediaByUser = MakeRequest<
|
||||
method: "GET",
|
||||
routingFunction: (userToken: string) =>
|
||||
`/v1/media_files/list/user/${userToken}`,
|
||||
});
|
||||
});
|
||||
@@ -1,14 +1,23 @@
|
||||
import { faFilm } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Button } from "~/components";
|
||||
import { activeJobs, viewMyMovies } from "~/pages/PageEnigma/store";
|
||||
import {
|
||||
activeJobs,
|
||||
generateMovieId,
|
||||
viewMyMovies,
|
||||
} from "~/pages/PageEnigma/store";
|
||||
|
||||
export const MyMoviesButton = () => {
|
||||
const activeCount = activeJobs.value.jobs.length;
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<Button variant="action" onClick={() => (viewMyMovies.value = true)}>
|
||||
<Button
|
||||
variant="action"
|
||||
onClick={() => {
|
||||
generateMovieId.value = "";
|
||||
viewMyMovies.value = true;
|
||||
}}>
|
||||
<div className="relative flex items-center gap-2">
|
||||
{activeCount > 0 ? (
|
||||
<svg
|
||||
|
||||
@@ -4,7 +4,7 @@ import { DragComponent } from "~/pages/PageEnigma/comps/DragComponent/DragCompon
|
||||
import { EngineProvider } from "~/contexts/EngineProvider";
|
||||
import { useInferenceJobManager } from "~/hooks";
|
||||
import { LoadingBar } from "~/components";
|
||||
import { MyMovies } from "~/pages/PageEnigma/comps/MyMovies/MyMovies";
|
||||
import { GenerateModals } from "~/pages/PageEnigma/comps/GenerateModals/GenerateModals";
|
||||
import { ErrorDialog } from "~/components/ErrorDialog";
|
||||
|
||||
export const PageEnigma = () => {
|
||||
@@ -14,7 +14,7 @@ export const PageEnigma = () => {
|
||||
<EngineProvider>
|
||||
<PageEnigmaComponent />
|
||||
<DragComponent />
|
||||
<MyMovies />
|
||||
<GenerateModals />
|
||||
<ErrorDialog />
|
||||
</EngineProvider>
|
||||
<LoadingBar
|
||||
|
||||
+10
-5
@@ -5,14 +5,17 @@ import { useRef, useState } from "react";
|
||||
import { BucketConfig } from "~/api/BucketConfig";
|
||||
import dayjs from "dayjs";
|
||||
import Tooltip from "~/components/Tooltip";
|
||||
import { environmentVariables } from "~/store";
|
||||
|
||||
interface Props {
|
||||
movie: MediaInfo;
|
||||
setMovieId: (id: string) => void;
|
||||
}
|
||||
|
||||
export function CompletedCard({ movie }: Props) {
|
||||
export function CompletedCard({ movie, setMovieId }: Props) {
|
||||
const bucketConfig = useRef<BucketConfig>(new BucketConfig());
|
||||
const [loadError, setLoadError] = useState(false);
|
||||
const downloadLink = `${environmentVariables.value.GOOGLE_API}/vocodes-public${movie.public_bucket_path}`;
|
||||
|
||||
const imageUrl = bucketConfig.current.getCdnUrl(
|
||||
movie.public_bucket_path + "-thumb.gif",
|
||||
@@ -23,9 +26,9 @@ export function CompletedCard({ movie }: Props) {
|
||||
return (
|
||||
<button
|
||||
className="flex w-full items-center justify-between px-5 py-3 text-start transition-all duration-150 hover:bg-brand-secondary/40"
|
||||
onClick={() =>
|
||||
console.log("change current modal to completed video modal")
|
||||
}>
|
||||
onClick={() => {
|
||||
setMovieId(movie.token);
|
||||
}}>
|
||||
<div className="flex gap-4">
|
||||
<div className="rounded-lg">
|
||||
<img
|
||||
@@ -51,7 +54,9 @@ export function CompletedCard({ movie }: Props) {
|
||||
<div className="pr-5">
|
||||
<Tooltip content="Download" position="top">
|
||||
<button
|
||||
onClick={() => console.log("download")}
|
||||
onClick={() => {
|
||||
window.open(downloadLink, "_blank");
|
||||
}}
|
||||
className="text-xl text-white/50 transition-all duration-150 hover:text-white/90">
|
||||
<FontAwesomeIcon icon={faArrowDownToLine} />
|
||||
</button>
|
||||
@@ -0,0 +1,35 @@
|
||||
import { TransitionDialogue } from "~/components";
|
||||
import { generateMovieId, viewMyMovies } from "~/pages/PageEnigma/store";
|
||||
import { faFilm } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { MyMovies } from "~/pages/PageEnigma/comps/GenerateModals/MyMovies";
|
||||
import { Sharing } from "~/pages/PageEnigma/comps/GenerateModals/Sharing";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import dayjs from "dayjs";
|
||||
import { MediaFile } from "~/pages/PageEnigma/models";
|
||||
import { GetMediaFileByToken } from "~/pages/PageEnigma/comps/SidePanelTabs/AudioTab/utilities";
|
||||
import { ToasterContext, ToastTypes } from "~/contexts/ToasterContext";
|
||||
|
||||
export function GenerateModals() {
|
||||
useSignals();
|
||||
const [movieId, setMovieId] = useState(generateMovieId.value);
|
||||
const [mediaFile, setMediaFile] = useState<MediaFile | null>(null);
|
||||
const { addToast } = useContext(ToasterContext);
|
||||
|
||||
useEffect(() => {
|
||||
if (movieId) {
|
||||
GetMediaFileByToken(movieId).then((res) => {
|
||||
if (!res.success) {
|
||||
addToast(ToastTypes.ERROR, "Unable to read media file");
|
||||
return;
|
||||
}
|
||||
setMediaFile(res.media_file ?? null);
|
||||
});
|
||||
}
|
||||
}, [movieId, addToast]);
|
||||
|
||||
if (!mediaFile) {
|
||||
return <MyMovies setMovieId={setMovieId} />;
|
||||
}
|
||||
return <Sharing mediaFile={mediaFile!} setMediaFile={setMediaFile} />;
|
||||
}
|
||||
File renamed without changes.
+23
-7
@@ -1,11 +1,20 @@
|
||||
import { TransitionDialogue } from "~/components";
|
||||
import { activeJobs, movies, viewMyMovies } from "~/pages/PageEnigma/store";
|
||||
import { CompletedCard } from "~/pages/PageEnigma/comps/MyMovies/CompletedCard";
|
||||
import { InProgressCard } from "~/pages/PageEnigma/comps/MyMovies/InProgressCard";
|
||||
import {
|
||||
activeJobs,
|
||||
generateMovieId,
|
||||
movies,
|
||||
viewMyMovies,
|
||||
} from "~/pages/PageEnigma/store";
|
||||
import { CompletedCard } from "~/pages/PageEnigma/comps/GenerateModals/CompletedCard";
|
||||
import { InProgressCard } from "~/pages/PageEnigma/comps/GenerateModals/InProgressCard";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { faFilm } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { TransitionDialogue } from "~/components";
|
||||
|
||||
export function MyMovies() {
|
||||
interface Props {
|
||||
setMovieId: (page: string) => void;
|
||||
}
|
||||
|
||||
export function MyMovies({ setMovieId }: Props) {
|
||||
useSignals();
|
||||
|
||||
return (
|
||||
@@ -15,7 +24,10 @@ export function MyMovies() {
|
||||
className="max-w-4xl"
|
||||
childPadding={false}
|
||||
isOpen={viewMyMovies.value}
|
||||
onClose={() => (viewMyMovies.value = false)}>
|
||||
onClose={() => {
|
||||
setMovieId("");
|
||||
viewMyMovies.value = false;
|
||||
}}>
|
||||
<div className="h-[560px] overflow-y-auto overflow-x-hidden rounded-b-lg">
|
||||
{activeJobs.value.jobs.length > 0 && (
|
||||
<div className="mb-3">
|
||||
@@ -29,7 +41,11 @@ export function MyMovies() {
|
||||
<div className="mx-5 mb-1 font-medium">Completed</div>
|
||||
<div className="flex flex-col">
|
||||
{movies.value.movies.map((movie) => (
|
||||
<CompletedCard key={movie.token} movie={movie} />
|
||||
<CompletedCard
|
||||
key={movie.token}
|
||||
movie={movie}
|
||||
setMovieId={setMovieId}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,133 @@
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { useLayoutEffect, useState } from "react";
|
||||
import { MediaFile } from "~/pages/PageEnigma/models";
|
||||
import { Button, Input, TransitionDialogue } from "~/components";
|
||||
import {
|
||||
faArrowDownToLine,
|
||||
faFilm,
|
||||
faLink,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import SocialButton from "./SocialButton";
|
||||
import { generateMovieId, viewMyMovies } from "~/pages/PageEnigma/store";
|
||||
import dayjs from "dayjs";
|
||||
import { environmentVariables } from "~/store";
|
||||
|
||||
interface Props {
|
||||
mediaFile: MediaFile;
|
||||
setMediaFile: (file: MediaFile | null) => void;
|
||||
}
|
||||
|
||||
export function Sharing({ mediaFile, setMediaFile }: Props) {
|
||||
useSignals();
|
||||
const shareUrl = `https://storyteller.ai/media/${mediaFile?.token || ""}`;
|
||||
const shareText = "Check out this media on StoryTeller.ai";
|
||||
const [buttonLabel, setButtonLabel] = useState("Copy");
|
||||
const downloadLink = `${environmentVariables.value.GOOGLE_API}/vocodes-public${mediaFile?.public_bucket_path}`;
|
||||
const openUrl = `/media/${mediaFile.token}`;
|
||||
|
||||
const handleCopyLink = () => {
|
||||
if (navigator.clipboard) {
|
||||
navigator.clipboard.writeText(shareUrl);
|
||||
}
|
||||
setButtonLabel("Copied!");
|
||||
setTimeout(() => setButtonLabel("Copy"), 2000);
|
||||
};
|
||||
|
||||
const generateTitle = () => {
|
||||
return (
|
||||
<div>
|
||||
<span className="font-xl font-bold">
|
||||
{mediaFile?.maybe_title ?? mediaFile?.token}
|
||||
</span>
|
||||
<span className="ml-2 text-sm text-white/60">
|
||||
{dayjs(mediaFile?.updated_at).format("MMM DD, YYYY HH:mm:SS")}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<TransitionDialogue
|
||||
title={generateTitle()}
|
||||
titleIcon={faFilm}
|
||||
className="max-w-4xl"
|
||||
childPadding={false}
|
||||
isOpen={viewMyMovies.value}
|
||||
width={1049}
|
||||
onClose={() => {
|
||||
if (generateMovieId.value) {
|
||||
viewMyMovies.value = false;
|
||||
return;
|
||||
}
|
||||
setMediaFile(null);
|
||||
}}>
|
||||
<div className="flex gap-[29px] px-5 pb-5">
|
||||
<div className="w-[616px]">
|
||||
<video controls width={616} crossOrigin="anonymous">
|
||||
<source
|
||||
src={`${environmentVariables.value.GOOGLE_API}/vocodes-public${mediaFile?.public_bucket_path}`}
|
||||
type="video/mp4"
|
||||
/>
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
</div>
|
||||
<div className="w-[355px]">
|
||||
<div className="mb-2 text-sm">Share movie to</div>
|
||||
<div className="flex w-full flex-wrap justify-between">
|
||||
<SocialButton
|
||||
social="x"
|
||||
shareUrl={shareUrl}
|
||||
shareText={shareText}
|
||||
/>
|
||||
<SocialButton
|
||||
social="whatsapp"
|
||||
shareUrl={shareUrl}
|
||||
shareText={shareText}
|
||||
/>
|
||||
<SocialButton
|
||||
social="facebook"
|
||||
shareUrl={shareUrl}
|
||||
shareText={shareText}
|
||||
/>
|
||||
<SocialButton
|
||||
social="reddit"
|
||||
shareUrl={shareUrl}
|
||||
shareText={shareText}
|
||||
/>
|
||||
<SocialButton
|
||||
social="email"
|
||||
shareUrl={shareUrl}
|
||||
shareText={shareText}
|
||||
/>
|
||||
</div>
|
||||
<div className="my-4 flex w-full gap-2">
|
||||
<div className="w-full">
|
||||
<Input type="text" value={shareUrl} readOnly />
|
||||
</div>
|
||||
|
||||
<Button icon={faLink} onClick={handleCopyLink} variant="primary">
|
||||
{buttonLabel}
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
icon={faArrowDownToLine}
|
||||
className="my-4 w-full"
|
||||
onClick={() => {
|
||||
window.open(downloadLink, "_blank");
|
||||
}}
|
||||
variant="secondary">
|
||||
Download
|
||||
</Button>
|
||||
<Button
|
||||
className="mb-4 w-full"
|
||||
onClick={() => {
|
||||
window.open(openUrl, "_blank");
|
||||
}}
|
||||
variant="secondary">
|
||||
View on Media Page
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</TransitionDialogue>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import {
|
||||
faFacebookF,
|
||||
faRedditAlien,
|
||||
faWhatsapp,
|
||||
faTwitter,
|
||||
} from "@fortawesome/free-brands-svg-icons";
|
||||
import { faXmark, faEnvelope } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
interface SocialButtonProps {
|
||||
social: "x" | "whatsapp" | "facebook" | "reddit" | "email";
|
||||
shareUrl: string;
|
||||
shareText: string;
|
||||
}
|
||||
|
||||
export default function SocialButton({
|
||||
social,
|
||||
shareUrl,
|
||||
shareText,
|
||||
}: SocialButtonProps) {
|
||||
const socialIcons = {
|
||||
x: faTwitter,
|
||||
whatsapp: faWhatsapp,
|
||||
facebook: faFacebookF,
|
||||
reddit: faRedditAlien,
|
||||
email: faEnvelope,
|
||||
};
|
||||
|
||||
const socialIcon = socialIcons[social] || faXmark;
|
||||
|
||||
const getShareLink = (social: string, url: string, text: string) => {
|
||||
switch (social) {
|
||||
case "x":
|
||||
return `https://twitter.com/intent/tweet?url=${encodeURIComponent(
|
||||
url,
|
||||
)}&text=${encodeURIComponent(text)}`;
|
||||
case "facebook":
|
||||
return `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(
|
||||
url,
|
||||
)}`;
|
||||
case "whatsapp":
|
||||
return `https://wa.me/?text=${encodeURIComponent(
|
||||
text,
|
||||
)} ${encodeURIComponent(url)}`;
|
||||
case "reddit":
|
||||
return `https://www.reddit.com/submit?url=${encodeURIComponent(
|
||||
url,
|
||||
)}&title=${encodeURIComponent(text)}`;
|
||||
case "email":
|
||||
return `mailto:?subject=${encodeURIComponent(
|
||||
text,
|
||||
)}&body=${encodeURIComponent(url)}`;
|
||||
default:
|
||||
return "#";
|
||||
}
|
||||
};
|
||||
|
||||
const handleClick = () => {
|
||||
const shareLink = getShareLink(social, shareUrl, shareText);
|
||||
window.open(shareLink, "_blank");
|
||||
};
|
||||
|
||||
return (
|
||||
<button className="flex flex-col items-center" onClick={handleClick}>
|
||||
<div
|
||||
className={[
|
||||
"flex h-[56px] w-[56px]",
|
||||
"items-center justify-center rounded-lg",
|
||||
"text-[32px] text-white",
|
||||
`bg-${social}`,
|
||||
"hover:opacity-80",
|
||||
].join(" ")}>
|
||||
<FontAwesomeIcon icon={socialIcon} />
|
||||
</div>
|
||||
|
||||
<p className="text-xs">
|
||||
{social.charAt(0).toUpperCase() + social.slice(1)}
|
||||
</p>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
File renamed without changes.
@@ -1,4 +1,11 @@
|
||||
import { listTts, listV2V, inferTts, listMediaByUser, getMediaFileByToken, inferV2V } from '~/api';
|
||||
import {
|
||||
listTts,
|
||||
listV2V,
|
||||
inferTts,
|
||||
listMediaByUser,
|
||||
getMediaFileByToken,
|
||||
inferV2V,
|
||||
} from "~/api";
|
||||
import {
|
||||
MediaFile,
|
||||
GetMediaFileResponse,
|
||||
@@ -6,7 +13,7 @@ import {
|
||||
VoiceConversionModelListResponse,
|
||||
EnqueueVoiceConversionRequest,
|
||||
EnqueueVoiceConversionResponse,
|
||||
} from './typesImported';
|
||||
} from "./typesImported";
|
||||
import {
|
||||
TtsModelListItem,
|
||||
TtsModelListResponsePayload,
|
||||
@@ -14,51 +21,59 @@ import {
|
||||
StatusLike,
|
||||
GenerateTtsAudioRequest,
|
||||
GenerateTtsAudioResponse,
|
||||
} from '~/pages/PageEnigma/models/tts';
|
||||
} from "~/pages/PageEnigma/models/tts";
|
||||
import { STORAGE_KEYS } from "~/contexts/Authentication/types";
|
||||
|
||||
|
||||
|
||||
export const ListAudioByUser = async(username:string, sessionToken: string) => {
|
||||
return await fetch(listMediaByUser(username),{
|
||||
method: 'GET',
|
||||
export const ListAudioByUser = async (
|
||||
username: string,
|
||||
sessionToken: string,
|
||||
) => {
|
||||
return await fetch(listMediaByUser(username), {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
'session': sessionToken,
|
||||
Accept: "application/json",
|
||||
session: sessionToken,
|
||||
},
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if(res.success && res.results){
|
||||
return res.results.filter((item:MediaFile)=>item['media_type']==='audio');
|
||||
}else{
|
||||
Promise.reject();
|
||||
}
|
||||
})
|
||||
.catch(e => ({ success : false }));
|
||||
}
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
if (res.success && res.results) {
|
||||
return res.results.filter(
|
||||
(item: MediaFile) => item["media_type"] === "audio",
|
||||
);
|
||||
} else {
|
||||
Promise.reject();
|
||||
}
|
||||
})
|
||||
.catch(() => ({ success: false }));
|
||||
};
|
||||
|
||||
export async function ListTtsModels(sessionToken:string) : Promise<Array<TtsModelListItem>| undefined> {
|
||||
export async function ListTtsModels(
|
||||
sessionToken: string,
|
||||
): Promise<Array<TtsModelListItem> | undefined> {
|
||||
return await fetch(listTts, {
|
||||
method: 'GET',
|
||||
method: "GET",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'session': sessionToken,
|
||||
Accept: "application/json",
|
||||
session: sessionToken,
|
||||
},
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
const response : TtsModelListResponsePayload = res;
|
||||
if (!response.success) {
|
||||
return;
|
||||
}
|
||||
return response?.models;
|
||||
})
|
||||
.catch(e => {
|
||||
return undefined;
|
||||
});
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
const response: TtsModelListResponsePayload = res;
|
||||
if (!response.success) {
|
||||
return;
|
||||
}
|
||||
return response?.models;
|
||||
})
|
||||
.catch(() => {
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
export function maybeMapError(statuslike: StatusLike) : GenerateTtsAudioErrorType | undefined {
|
||||
export function maybeMapError(
|
||||
statuslike: StatusLike,
|
||||
): GenerateTtsAudioErrorType | undefined {
|
||||
switch (statuslike.status) {
|
||||
case 400:
|
||||
return GenerateTtsAudioErrorType.BadRequest;
|
||||
@@ -71,121 +86,124 @@ export function maybeMapError(statuslike: StatusLike) : GenerateTtsAudioErrorTyp
|
||||
}
|
||||
}
|
||||
|
||||
export async function GenerateTtsAudio(request: GenerateTtsAudioRequest, sessionToken:string) : Promise<GenerateTtsAudioResponse>
|
||||
{
|
||||
export async function GenerateTtsAudio(
|
||||
request: GenerateTtsAudioRequest,
|
||||
sessionToken: string,
|
||||
): Promise<GenerateTtsAudioResponse> {
|
||||
return await fetch(inferTts, {
|
||||
method: 'POST',
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'session': sessionToken,
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
session: sessionToken,
|
||||
},
|
||||
body: JSON.stringify(request),
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if (!('inference_job_token' in res)) {
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
if (!("inference_job_token" in res)) {
|
||||
return { error: GenerateTtsAudioErrorType.UnknownError };
|
||||
}
|
||||
const ret: GenerateTtsAudioResponse = {
|
||||
success: true,
|
||||
inference_job_token: res.inference_job_token,
|
||||
inference_job_token_type: res.inference_job_token_type,
|
||||
};
|
||||
return ret;
|
||||
})
|
||||
.catch((e) => {
|
||||
const maybeError = maybeMapError(e);
|
||||
if (maybeError !== undefined) {
|
||||
return { error: maybeError };
|
||||
}
|
||||
return { error: GenerateTtsAudioErrorType.UnknownError };
|
||||
}
|
||||
const ret:GenerateTtsAudioResponse = {
|
||||
success: true,
|
||||
inference_job_token: res.inference_job_token,
|
||||
inference_job_token_type: res.inference_job_token_type,
|
||||
}
|
||||
return ret;
|
||||
})
|
||||
.catch(e => {
|
||||
let maybeError = maybeMapError(e);
|
||||
if (maybeError !== undefined) {
|
||||
return { error: maybeError };
|
||||
}
|
||||
return { error: GenerateTtsAudioErrorType.UnknownError };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export async function GetMediaFileByToken (fileToken: string, sessionToken: string) : Promise<GetMediaFileResponse>
|
||||
{
|
||||
export async function GetMediaFileByToken(
|
||||
fileToken: string,
|
||||
): Promise<GetMediaFileResponse> {
|
||||
const sessionToken = localStorage.getItem(STORAGE_KEYS.SESSION_TOKEN) ?? "";
|
||||
return await fetch(getMediaFileByToken(fileToken), {
|
||||
method: "GET",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'session': sessionToken,
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
session: sessionToken,
|
||||
},
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
const response: GetMediaFileResponse = res;
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
const response: GetMediaFileResponse = res;
|
||||
|
||||
if (response && response.success && response.media_file) {
|
||||
// NB: Timestamps aren't converted to Date objects on their own!
|
||||
response.media_file.created_at = new Date(
|
||||
response.media_file.created_at
|
||||
response.media_file.created_at,
|
||||
);
|
||||
response.media_file.updated_at = new Date(
|
||||
response.media_file.updated_at
|
||||
response.media_file.updated_at,
|
||||
);
|
||||
return response;
|
||||
} else {
|
||||
return { success: false };
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
return { success: false };
|
||||
});
|
||||
;
|
||||
})
|
||||
.catch(() => {
|
||||
return { success: false };
|
||||
});
|
||||
}
|
||||
|
||||
export async function ListVoiceConversionModels(sessionToken: string) : Promise<Array<VoiceConversionModelListItem>| undefined> {
|
||||
export async function ListVoiceConversionModels(
|
||||
sessionToken: string,
|
||||
): Promise<Array<VoiceConversionModelListItem> | undefined> {
|
||||
return await fetch(listV2V, {
|
||||
method: 'GET',
|
||||
method: "GET",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'session': sessionToken,
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
session: sessionToken,
|
||||
},
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
const response : VoiceConversionModelListResponse = res;
|
||||
if (!response.success) {
|
||||
return;
|
||||
}
|
||||
return response?.models;
|
||||
})
|
||||
.catch(e => {
|
||||
return undefined;
|
||||
});
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
const response: VoiceConversionModelListResponse = res;
|
||||
if (!response.success) {
|
||||
return;
|
||||
}
|
||||
return response?.models;
|
||||
})
|
||||
.catch(() => {
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
export async function GenerateVoiceConversion(
|
||||
request: EnqueueVoiceConversionRequest,
|
||||
sessionToken: string,
|
||||
) : Promise<EnqueueVoiceConversionResponse>
|
||||
{
|
||||
): Promise<EnqueueVoiceConversionResponse> {
|
||||
return await fetch(inferV2V, {
|
||||
method: 'POST',
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'session': sessionToken,
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
session: sessionToken,
|
||||
},
|
||||
body: JSON.stringify(request),
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
if (!res) {
|
||||
return { success : false };
|
||||
}
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
if (!res) {
|
||||
return { success: false };
|
||||
}
|
||||
|
||||
if (res && 'success' in res) {
|
||||
return res;
|
||||
} else {
|
||||
return { success : false };
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
return { success : false };
|
||||
});
|
||||
}
|
||||
if (res && "success" in res) {
|
||||
return res;
|
||||
} else {
|
||||
return { success: false };
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
return { success: false };
|
||||
});
|
||||
}
|
||||
@@ -2,6 +2,7 @@ export * from "./assets";
|
||||
export * from "./inferenceJobs";
|
||||
export * from "./message";
|
||||
export * from "./movies";
|
||||
export * from "./pagination";
|
||||
export * from "./sidePanel";
|
||||
export * from "./track";
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface Pagination {
|
||||
current: number;
|
||||
total_page_count: number;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { ActiveJob } from "~/pages/PageEnigma/models";
|
||||
import { MediaInfo } from "~/pages/PageEnigma/models/movies";
|
||||
|
||||
export const viewMyMovies = signal(false);
|
||||
export const generateMovieId = signal("");
|
||||
|
||||
export const activeJobs = signal<{ jobs: ActiveJob[] }>({ jobs: [] });
|
||||
export const movies = signal<{ movies: MediaInfo[] }>({ movies: [] });
|
||||
Generated
+22
@@ -11,6 +11,7 @@
|
||||
"@ffmpeg/ffmpeg": "0.11.6",
|
||||
"@ffmpeg/util": "0.12.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
||||
"@fortawesome/pro-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@headlessui/react": "^1.7.18",
|
||||
@@ -1334,6 +1335,27 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-brands-svg-icons": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://npm.fontawesome.com/@fortawesome/free-brands-svg-icons/-/6.5.2/free-brands-svg-icons-6.5.2.tgz",
|
||||
"integrity": "sha512-zi5FNYdmKLnEc0jc0uuHH17kz/hfYTg4Uei0wMGzcoCL/4d3WM3u1VMc0iGGa31HuhV5i7ZK8ZlTCQrHqRHSGQ==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.5.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-brands-svg-icons/node_modules/@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-common-types/-/6.5.2/fontawesome-common-types-6.5.2.tgz",
|
||||
"integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/pro-solid-svg-icons": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://npm.fontawesome.com/@fortawesome/pro-solid-svg-icons/-/6.5.1/pro-solid-svg-icons-6.5.1.tgz",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"@ffmpeg/ffmpeg": "0.11.6",
|
||||
"@ffmpeg/util": "0.12.0",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
||||
"@fortawesome/pro-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@headlessui/react": "^1.7.18",
|
||||
|
||||
+16
-5
@@ -147,7 +147,7 @@ export default {
|
||||
selectedTab: "#55556B",
|
||||
},
|
||||
|
||||
ui:{
|
||||
ui: {
|
||||
background: "#1a1a27",
|
||||
panel: "#242433",
|
||||
"panel-border": "#393948",
|
||||
@@ -156,20 +156,20 @@ export default {
|
||||
divider: "#515168",
|
||||
},
|
||||
|
||||
media:{
|
||||
media: {
|
||||
"audio-tts": "#6AAA88",
|
||||
"audio-v2v": "#6691B9",
|
||||
"audio-upload": "#9760C2",
|
||||
"audio-demo" : "#B96675",
|
||||
"audio-demo": "#B96675",
|
||||
"is-new": "#FFDC26",
|
||||
},
|
||||
|
||||
inference:{
|
||||
inference: {
|
||||
pending: "#6b728b",
|
||||
generating: "#46527C",
|
||||
error: "#924C4B",
|
||||
},
|
||||
|
||||
|
||||
"axis-x": "#D33242",
|
||||
"axis-y": "#308752",
|
||||
"axis-z": "#2E70FF",
|
||||
@@ -177,6 +177,12 @@ export default {
|
||||
green: "#308752",
|
||||
blue: "#2E70FF",
|
||||
|
||||
facebook: "#4267b2",
|
||||
reddit: "#ff5700",
|
||||
whatsapp: "#25d366",
|
||||
x: "#1da1f2",
|
||||
email: "#858585",
|
||||
|
||||
white: colors.white,
|
||||
gray: colors.gray,
|
||||
black: colors.black,
|
||||
@@ -196,5 +202,10 @@ export default {
|
||||
"bg-object-selected",
|
||||
"bg-object-unselected",
|
||||
"bg-object-clip",
|
||||
"bg-facebook",
|
||||
"bg-reddit",
|
||||
"bg-whatsapp",
|
||||
"bg-x",
|
||||
"bg-email",
|
||||
],
|
||||
} satisfies Config;
|
||||
Reference in new issue
Block a user