From 15fda64ca8cec05cc666c02428e9292aab29f5ac Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Tue, 25 Apr 2023 03:57:25 -0700 Subject: [PATCH] inline results --- .../SessionVoiceConversionResultsList.tsx | 242 ++++++++++++++++++ .../vc/vc_model_list/VcModelListPage.tsx | 7 +- 2 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 packages/fakeyou.com/src/v2/view/_common/SessionVoiceConversionResultsList.tsx diff --git a/packages/fakeyou.com/src/v2/view/_common/SessionVoiceConversionResultsList.tsx b/packages/fakeyou.com/src/v2/view/_common/SessionVoiceConversionResultsList.tsx new file mode 100644 index 0000000000..5545894b14 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/_common/SessionVoiceConversionResultsList.tsx @@ -0,0 +1,242 @@ +import React, { useEffect, useState } from "react"; +import { t } from "i18next"; +import { Trans } from "react-i18next"; +import { Link } from "react-router-dom"; +import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; +import { JobState } from "@storyteller/components/src/jobs/JobStates"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faClock, + faLink, + faHeadphonesSimple, +} from "@fortawesome/free-solid-svg-icons"; +import { motion } from "framer-motion"; +import { container, sessionItem } from "../../../data/animation"; +import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper"; +import { Analytics } from "../../../common/Analytics"; +import { SessionTtsAudioPlayer } from "./SessionTtsAudioPlayer"; +import { WebUrl } from "../../../common/WebUrl"; +import { + GetPendingTtsJobCount, + GetPendingTtsJobCountIsOk, + GetPendingTtsJobCountSuccessResponse, +} from "@storyteller/components/src/api/tts/GetPendingTtsJobCount"; +import { InferenceJob } from "@storyteller/components/src/jobs/InferenceJob"; + +interface Props { + inferenceJobs: Array; + sessionSubscriptionsWrapper: SessionSubscriptionsWrapper; +} + +// TODO: This is duplicated in SessionTtsInferenceResultsList ! +// Default to querying every 15 seconds, but make it configurable serverside +const DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS = 15000; + +function SessionVoiceConversionResultsList(props: Props) { + const [pendingTtsJobs, setPendingTtsJobs] = + useState({ + success: true, + pending_job_count: 0, + cache_time: new Date(0), // NB: Epoch is used for vector clock's initial state + refresh_interval_millis: DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS, + }); + + useEffect(() => { + const fetch = async () => { + const response = await GetPendingTtsJobCount(); + if (GetPendingTtsJobCountIsOk(response)) { + if ( + response.cache_time.getTime() > pendingTtsJobs.cache_time.getTime() + ) { + setPendingTtsJobs(response); + } + } + }; + // TODO: We're having an outage and need to lower this. + //const interval = setInterval(async () => fetch(), 15000); + const refreshInterval = Math.max(DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS, pendingTtsJobs.refresh_interval_millis); + const interval = setInterval(async () => fetch(), refreshInterval); + fetch(); + return () => clearInterval(interval); + }, [pendingTtsJobs]); + + let results: Array = []; + + // TODO(bt,2023-04-08): Clean this utter garbage duplication up. + + // ============================= GENERIC INFERENCE ============================= + + props.inferenceJobs.forEach((job) => { + if (!job.maybeResultToken) { + let cssStyle = "alert alert-secondary mb-0"; + let stateDescription = "Pending..."; + + switch (job.jobState) { + case JobState.PENDING: + case JobState.UNKNOWN: + stateDescription = + job.maybeExtraStatusDescription == null + ? t("common.SessionTtsInferenceResults.progress.pending") + : job.maybeExtraStatusDescription; + break; + case JobState.STARTED: + cssStyle = "alert alert-success mb-0"; + stateDescription = + job.maybeExtraStatusDescription == null + ? t("common.SessionTtsInferenceResults.progress.started") + : job.maybeExtraStatusDescription; + break; + case JobState.ATTEMPT_FAILED: + cssStyle = "alert alert-danger mb-0"; + stateDescription = `Failed ${job.attemptCount} attempt(s). Will retry...`; + break; + case JobState.COMPLETE_FAILURE: + case JobState.DEAD: + cssStyle = "alert alert-danger mb-0"; + // TODO(bt,2023-01-23): Translate when I can test it + stateDescription = t( + "common.SessionTtsInferenceResults.progress.dead" + ); + break; + case JobState.COMPLETE_SUCCESS: + cssStyle = "message is-success mb-0"; + // Not sure why we're here instead of other branch! + stateDescription = t( + "common.SessionTtsInferenceResults.progress.success" + ); + break; + } + + results.push( +
+
+
+ + {stateDescription} + +
+
+
+ ); + } else { + let audioLink = new BucketConfig().getGcsUrl( + job.maybeResultPublicBucketMediaPath + ); + let ttsPermalink = `/tts/result/${job.maybeResultToken}`; + + let wavesurfers = ; + + results.push( +
+ {/*
+

{job.title}

+ +
*/} +
+ +
+
{job.maybeModelTitle}
+

{job.maybeRawInferenceText}

+
+ + {/* */} + + {wavesurfers} + +
+ { + Analytics.ttsClickResultLink(); + }} + className="fw-semibold" + > + + {t("common.SessionTtsInferenceResults.result.shareDownload")} + +
+
+
+
+ ); + } + }); + + let noResultsSection = ( +
+
+ +
+ {t("common.SessionTtsInferenceResults.noResults.title")} +
+

{t("common.SessionTtsInferenceResults.noResults.subtitle")}

+
+
+ ); + + if (results.length === 0) { + return <>{noResultsSection}; + } + + let upgradeNotice = <>; + + // Ask non-premium users to upgrade + if ( + results.length !== 0 && + !props.sessionSubscriptionsWrapper.hasPaidFeatures() + ) { + upgradeNotice = ( +
+ + + + Don't want to wait? Step to the back of the line with a{" "} + { + Analytics.ttsTooSlowUpgradePremium(); + }} + className="alert-link fw-semibold" + > + FakeYou membership. + + {" "} + (TTS Queued:{" "} + ~{pendingTtsJobs.pending_job_count}) + +
+ ); + } + + // Users have requested reverse chronological results + results.reverse(); + + return ( + +
+
+ {upgradeNotice} +
{results}
+
+
+
+ ); +} + +export { SessionVoiceConversionResultsList }; diff --git a/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_list/VcModelListPage.tsx b/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_list/VcModelListPage.tsx index bdb98f8bc4..923be851fd 100644 --- a/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_list/VcModelListPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_list/VcModelListPage.tsx @@ -25,6 +25,7 @@ import { VcModelListSearch } from "./components/VcModelListSearchComponent"; import { EnqueueVoiceConversion, EnqueueVoiceConversionIsSuccess, EnqueueVoiceConversionRequest } from "@storyteller/components/src/api/voice_conversion/EnqueueVoiceConversion"; import { Analytics } from "../../../../../common/Analytics"; import { FrontendInferenceJobType, InferenceJob } from "@storyteller/components/src/jobs/InferenceJob"; +import { SessionVoiceConversionResultsList } from "../../../_common/SessionVoiceConversionResultsList"; interface Props { sessionWrapper: SessionWrapper; @@ -357,7 +358,11 @@ function VcModelListPage(props: Props) { Session VC Results
- {noResultsSection} + + {/*{noResultsSection}*/} {/*