From 2c1f4a2cb7f9704524cbbac7ad04ab6998709806 Mon Sep 17 00:00:00 2001 From: BFlat Date: Thu, 12 Oct 2023 14:18:41 +0700 Subject: [PATCH 01/51] halloween landing 2023 --- .../fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx b/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx index 5539390eab..a9f2176041 100644 --- a/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx @@ -137,8 +137,11 @@ function LandingPage(props: Props) { const randomHeroImage = useMemo(() => { const images = [ // Main Images: - "mascot/kitsune_pose2.webp", + // "mascot/kitsune_pose2.webp", // "mascot/may4th.webp", + "mascot/halloween_1.webp", + "mascot/halloween_2.webp", + "mascot/halloween_3.webp", ]; return images[Math.floor(Math.random() * images.length)]; From ff6f7821a2af5d1af879779db0a40ac458abfa55 Mon Sep 17 00:00:00 2001 From: BFlat Date: Thu, 12 Oct 2023 16:12:35 +0700 Subject: [PATCH 02/51] container component for page wrapping --- .../components/common/Container/Container.tsx | 30 ++++++++++++ .../src/components/common/Container/index.tsx | 1 + .../common/PageContainer/PageContainer.tsx | 24 ---------- .../src/components/common/Panel/Panel.tsx | 9 ++-- .../layout/PageHeader/PageHeader.tsx | 47 ++++++++++++------- .../src/components/layout/PageHeader/index.js | 1 - .../components/layout/PageHeader/index.tsx | 1 + .../PageHeaderModelView.tsx | 6 ++- .../fakeyou.com/src/v2/view/PageContainer.tsx | 24 ++++++---- .../v2/view/_common/PageHeaderWithImage.tsx | 2 +- .../tts_model_search/TtsModelSearchPage.tsx | 18 +++++++ .../vc/vc_model_delete/VcModelDeletePage.tsx | 2 +- .../vc/vc_model_edit/VcModelEditPage.tsx | 2 +- .../vc/vc_model_view/VcModelViewPage.tsx | 6 +-- 14 files changed, 110 insertions(+), 63 deletions(-) create mode 100644 packages/fakeyou.com/src/components/common/Container/Container.tsx create mode 100644 packages/fakeyou.com/src/components/common/Container/index.tsx delete mode 100644 packages/fakeyou.com/src/components/common/PageContainer/PageContainer.tsx delete mode 100644 packages/fakeyou.com/src/components/layout/PageHeader/index.js create mode 100644 packages/fakeyou.com/src/components/layout/PageHeader/index.tsx create mode 100644 packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx diff --git a/packages/fakeyou.com/src/components/common/Container/Container.tsx b/packages/fakeyou.com/src/components/common/Container/Container.tsx new file mode 100644 index 0000000000..a8ae3ca28e --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Container/Container.tsx @@ -0,0 +1,30 @@ +import React from "react"; + +interface ContainerProps { + children: React.ReactNode; + type?: "full" | "padded" | "panel"; +} + +export default function PageContainer({ + children, + type = "panel", +}: ContainerProps) { + let containerClass = ""; + + switch (type) { + case "full": + containerClass = "container-fluid"; + break; + case "padded": + containerClass = "container"; + break; + case "panel": + containerClass = ""; + break; + default: + containerClass = "container-fluid"; + break; + } + + return
{children}
; +} diff --git a/packages/fakeyou.com/src/components/common/Container/index.tsx b/packages/fakeyou.com/src/components/common/Container/index.tsx new file mode 100644 index 0000000000..c81c92aeb0 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Container/index.tsx @@ -0,0 +1 @@ +export { default } from "./Container"; diff --git a/packages/fakeyou.com/src/components/common/PageContainer/PageContainer.tsx b/packages/fakeyou.com/src/components/common/PageContainer/PageContainer.tsx deleted file mode 100644 index c2088b8e9a..0000000000 --- a/packages/fakeyou.com/src/components/common/PageContainer/PageContainer.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { container } from "data/animation"; -import { motion } from "framer-motion"; -import React from "react"; - -interface PageContainerProps { - children: React.ReactNode; - padding?: boolean; -} - -export default function PageContainer({ - children, - padding, -}: PageContainerProps) { - return ( - - {children} - - ); -} diff --git a/packages/fakeyou.com/src/components/common/Panel/Panel.tsx b/packages/fakeyou.com/src/components/common/Panel/Panel.tsx index 6fda465884..25e1d4281e 100644 --- a/packages/fakeyou.com/src/components/common/Panel/Panel.tsx +++ b/packages/fakeyou.com/src/components/common/Panel/Panel.tsx @@ -1,23 +1,22 @@ import React from "react"; -import { motion } from "framer-motion"; -import { panel } from "data/animation"; interface PanelProps { children: React.ReactNode; padding?: boolean; mb?: boolean; mt?: boolean; + full?: boolean; } -export default function Panel({ children, padding, mb, mt }: PanelProps) { +export default function Panel({ children, padding, mb, mt, full }: PanelProps) { return ( - +
{children}
- +
); } diff --git a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx index e0c8b6e0e4..e28e3ddca2 100644 --- a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx +++ b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx @@ -10,24 +10,37 @@ interface Props { actionButtons?: JSX.Element; } - -export default function PageHeader({ actionButtons, childProps, showButtons, subText, titleComponent: Title, title, titleIcon }: Props) { - return
-
-
- { Title ? : <h1 className="fw-bold text-center text-md-start"> - { titleIcon } - { title } - </h1> } - <p className="text-center text-md-start pt-1">{ subText }</p> - { showButtons && ( - <div className="d-flex flex-column flex-md-row gap-3 justify-content-center justify-content-md-start mt-4"> - { actionButtons } - </div> - )} +export default function PageHeader({ + actionButtons, + childProps, + showButtons, + subText, + titleComponent: Title, + title, + titleIcon, +}: Props) { + return ( + <div className="container-panel hero-section py-4"> + <div className="panel"> + <div className="p-3 py-4 p-md-4"> + {Title ? ( + <Title {...childProps} /> + ) : ( + <h1 className="fw-bold text-center text-md-start"> + {titleIcon} + {title} + </h1> + )} + <p className="text-center text-md-start pt-1">{subText}</p> + {showButtons && ( + <div className="d-flex flex-column flex-md-row gap-3 justify-content-center justify-content-md-start mt-4"> + {actionButtons} + </div> + )} + </div> </div> </div> - </div>; -}; + ); +} // export default PageHeader; diff --git a/packages/fakeyou.com/src/components/layout/PageHeader/index.js b/packages/fakeyou.com/src/components/layout/PageHeader/index.js deleted file mode 100644 index 58edd62eef..0000000000 --- a/packages/fakeyou.com/src/components/layout/PageHeader/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './PageHeader'; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/layout/PageHeader/index.tsx b/packages/fakeyou.com/src/components/layout/PageHeader/index.tsx new file mode 100644 index 0000000000..c9b885cbfc --- /dev/null +++ b/packages/fakeyou.com/src/components/layout/PageHeader/index.tsx @@ -0,0 +1 @@ +export { default } from "./PageHeader"; diff --git a/packages/fakeyou.com/src/components/layout/PageHeaderModelView/PageHeaderModelView.tsx b/packages/fakeyou.com/src/components/layout/PageHeaderModelView/PageHeaderModelView.tsx index bdabbc4f50..331e477565 100644 --- a/packages/fakeyou.com/src/components/layout/PageHeaderModelView/PageHeaderModelView.tsx +++ b/packages/fakeyou.com/src/components/layout/PageHeaderModelView/PageHeaderModelView.tsx @@ -13,6 +13,7 @@ interface PageHeaderModelViewProps { extras?: React.ReactNode; view?: "regular" | "edit" | "delete"; modelType?: "TTS" | "V2V"; + full?: boolean; } export default function PageHeaderModelView({ @@ -25,15 +26,16 @@ export default function PageHeaderModelView({ extras, view = "regular", modelType = "TTS", + full, }: PageHeaderModelViewProps) { const icon = ( <>{titleIcon && <FontAwesomeIcon icon={titleIcon} className="me-3" />}</> ); return ( - <div className="pt-2 pt-lg-4 pb-4"> + <div className="pt-3 pb-4 pt-lg-4"> {view === "regular" && ( - <Panel padding> + <Panel padding full={full}> <div className="row gy-3"> <div className="col-12 col-lg-8"> <h2 className="fw-bold"> diff --git a/packages/fakeyou.com/src/v2/view/PageContainer.tsx b/packages/fakeyou.com/src/v2/view/PageContainer.tsx index 6b5bce6ef8..537ed1e29f 100644 --- a/packages/fakeyou.com/src/v2/view/PageContainer.tsx +++ b/packages/fakeyou.com/src/v2/view/PageContainer.tsx @@ -89,6 +89,7 @@ import SideNav from "components/layout/SideNav/SideNav"; import MobileMenu from "components/layout/MobileMenu/MobileMenu"; import { TopNav } from "./nav/TopNav"; import { TestingPage } from "./pages/testing/TestingPage"; +import TtsModelSearchPage from "./pages/tts/tts_model_search/TtsModelSearchPage"; interface Props { sessionWrapper: SessionWrapper; @@ -317,6 +318,10 @@ class PageContainer extends React.Component< /> </Route> + <Route path="/dev-tts"> + <TtsModelSearchPage sessionWrapper={this.props.sessionWrapper} /> + </Route> + <Route path="/tts/result/:token/edit"> <TtsResultEditPage sessionWrapper={this.props.sessionWrapper} /> </Route> @@ -459,7 +464,7 @@ class PageContainer extends React.Component< </Route> <Route path="/media/:token"> - <Media/> + <Media /> </Route> <Route path="/moderation/user/list"> @@ -580,7 +585,7 @@ class PageContainer extends React.Component< </Route> <Route path="/testing"> - <TestingPage + <TestingPage sessionSubscriptionsWrapper={ this.props.sessionSubscriptionsWrapper } @@ -591,12 +596,15 @@ class PageContainer extends React.Component< </Route> <Route path="/face-animation"> - <LipsyncEditor {...{ - enqueueInferenceJob: this.props.enqueueInferenceJob, - sessionSubscriptionsWrapper: this.props.sessionSubscriptionsWrapper, - inferenceJobs: this.props.inferenceJobs, - inferenceJobsByCategory: this.props.inferenceJobsByCategory - }} /> + <LipsyncEditor + {...{ + enqueueInferenceJob: this.props.enqueueInferenceJob, + sessionSubscriptionsWrapper: + this.props.sessionSubscriptionsWrapper, + inferenceJobs: this.props.inferenceJobs, + inferenceJobsByCategory: this.props.inferenceJobsByCategory, + }} + /> </Route> <Route path="/commissions"> diff --git a/packages/fakeyou.com/src/v2/view/_common/PageHeaderWithImage.tsx b/packages/fakeyou.com/src/v2/view/_common/PageHeaderWithImage.tsx index 1fcd7711c5..4dfc6ce3e9 100644 --- a/packages/fakeyou.com/src/v2/view/_common/PageHeaderWithImage.tsx +++ b/packages/fakeyou.com/src/v2/view/_common/PageHeaderWithImage.tsx @@ -11,7 +11,7 @@ interface Props { function PageHeaderWithImage(props: Props) { return ( - <div className="container-panel hero-section pt-3 pb-4 pt-lg-4"> + <div className="container-panel pt-3 pb-4 pt-lg-4"> <div className="panel"> <div className="row gx-3 flex-md-row-reverse"> <div className="col-12 col-md-5 hero-img-container d-none d-md-block"> diff --git a/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx b/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx new file mode 100644 index 0000000000..be8cd4b328 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; +import Container from "components/common/Container"; +import Panel from "components/common/Panel/Panel"; + +interface TtsModelSearchPageProps { + sessionWrapper: SessionWrapper; +} + +export default function TtsModelSearchPage(props: TtsModelSearchPageProps) { + return ( + <Container type="panel"> + <Panel padding={true}> + <div>test</div> + </Panel> + </Container> + ); +} diff --git a/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_delete/VcModelDeletePage.tsx b/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_delete/VcModelDeletePage.tsx index 7a522c70ac..91c70835e7 100644 --- a/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_delete/VcModelDeletePage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_delete/VcModelDeletePage.tsx @@ -5,7 +5,7 @@ import Panel from "components/common/Panel/Panel"; import { faSave, faTrash } from "@fortawesome/pro-solid-svg-icons"; import PageHeaderModelView from "components/layout/PageHeaderModelView/PageHeaderModelView"; import Button from "components/common/Button/Button"; -import PageContainer from "components/common/PageContainer/PageContainer"; +import PageContainer from "components/common/Container"; interface VcModelDeletePageProps { sessionWrapper: SessionWrapper; diff --git a/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_edit/VcModelEditPage.tsx b/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_edit/VcModelEditPage.tsx index 1e1c2ea9dc..6d3d6daa3f 100644 --- a/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_edit/VcModelEditPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_edit/VcModelEditPage.tsx @@ -6,7 +6,7 @@ import Panel from "components/common/Panel/Panel"; import { faEye, faFilePen, faSave } from "@fortawesome/pro-solid-svg-icons"; import PageHeaderModelView from "components/layout/PageHeaderModelView/PageHeaderModelView"; import Button from "components/common/Button/Button"; -import PageContainer from "components/common/PageContainer/PageContainer"; +import PageContainer from "components/common/Container"; interface VcModelEditPageProps { sessionWrapper: SessionWrapper; diff --git a/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_view/VcModelViewPage.tsx b/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_view/VcModelViewPage.tsx index cb7fcf22be..b16b6b836f 100644 --- a/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_view/VcModelViewPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/vc/vc_model_view/VcModelViewPage.tsx @@ -17,7 +17,7 @@ import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapp import { RatingButtons } from "v2/view/_common/ratings/RatingButtons"; import { RatingStats } from "v2/view/_common/ratings/RatingStats"; import ShareButton from "components/common/ShareButton/ShareButton"; -import PageContainer from "components/common/PageContainer/PageContainer"; +import Container from "components/common/Container/Container"; import VcGenerateAudioPanel from "../VcGenerateAudioPanel"; interface VcModelViewPageProps { @@ -97,7 +97,7 @@ export default function VcModelViewPage(props: VcModelViewPageProps) { const shareButton = <ShareButton url={shareUrl} />; return ( - <PageContainer> + <Container type="full"> <PageHeaderModelView title={title} subText={subText} @@ -180,6 +180,6 @@ export default function VcModelViewPage(props: VcModelViewPageProps) { sessionWrapper={props.sessionWrapper} /> </Panel> - </PageContainer> + </Container> ); } From cf3f79dc5fb1593bc54b6405e4b24847d51175fe Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Thu, 12 Oct 2023 22:09:31 +0700 Subject: [PATCH 03/51] search page and many component updates --- .../src/components/common/Button/Button.scss | 19 ++--- .../src/components/common/Button/Button.tsx | 66 ++++++++++++--- .../src/components/common/Button/index.tsx | 1 + .../common/CheckableTag/CheckableTag.scss | 39 +++++++++ .../common/CheckableTag/CheckableTag.tsx | 26 ++++++ .../components/common/CheckableTag/index.tsx | 1 + .../src/components/common/Input/Input.tsx | 24 ++++++ .../src/components/common/Input/index.tsx | 1 + .../common/ModelSearch/ModelSearch.tsx | 20 +++++ .../common/ModelSearch/dummyData.ts | 4 + .../components/common/ModelSearch/index.tsx | 1 + .../ModelSearchResults.scss | 29 +++++++ .../ModelSearchResults/ModelSearchResults.tsx | 28 +++++++ .../common/ModelSearchResults/index.tsx | 1 + .../components/common/ModelTags/ModelTags.tsx | 23 ++++++ .../src/components/common/ModelTags/index.tsx | 1 + .../src/components/common/Panel/index.tsx | 1 + .../src/components/common/Select/Select.scss | 68 ++++++++++++++++ .../src/components/common/Select/Select.tsx | 53 ++++++++++++ .../src/components/common/Select/index.tsx | 1 + .../common/ShareButton/ShareButton.tsx | 4 +- .../components/common/TextArea/TextArea.tsx | 19 +++++ .../src/components/common/TextArea/index.tsx | 1 + .../layout/MobileMenu/MobileMenu.tsx | 4 +- .../layout/PageHeader/PageHeader.tsx | 81 +++++++++++-------- .../src/components/layout/SideNav/SideNav.tsx | 6 +- .../src/components/layout/index.tsx | 5 -- .../fakeyou.com/src/hooks/useSearch/index.ts | 1 + .../src/hooks/useSearch/useSearch.tsx | 32 ++++++++ .../fakeyou.com/src/scss/site-refresh.scss | 2 +- .../tts_model_search/TtsModelSearchPage.tsx | 78 +++++++++++++++++- 31 files changed, 569 insertions(+), 71 deletions(-) create mode 100644 packages/fakeyou.com/src/components/common/Button/index.tsx create mode 100644 packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.scss create mode 100644 packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.tsx create mode 100644 packages/fakeyou.com/src/components/common/CheckableTag/index.tsx create mode 100644 packages/fakeyou.com/src/components/common/Input/Input.tsx create mode 100644 packages/fakeyou.com/src/components/common/Input/index.tsx create mode 100644 packages/fakeyou.com/src/components/common/ModelSearch/ModelSearch.tsx create mode 100644 packages/fakeyou.com/src/components/common/ModelSearch/dummyData.ts create mode 100644 packages/fakeyou.com/src/components/common/ModelSearch/index.tsx create mode 100644 packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss create mode 100644 packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.tsx create mode 100644 packages/fakeyou.com/src/components/common/ModelSearchResults/index.tsx create mode 100644 packages/fakeyou.com/src/components/common/ModelTags/ModelTags.tsx create mode 100644 packages/fakeyou.com/src/components/common/ModelTags/index.tsx create mode 100644 packages/fakeyou.com/src/components/common/Panel/index.tsx create mode 100644 packages/fakeyou.com/src/components/common/Select/Select.scss create mode 100644 packages/fakeyou.com/src/components/common/Select/Select.tsx create mode 100644 packages/fakeyou.com/src/components/common/Select/index.tsx create mode 100644 packages/fakeyou.com/src/components/common/TextArea/TextArea.tsx create mode 100644 packages/fakeyou.com/src/components/common/TextArea/index.tsx delete mode 100644 packages/fakeyou.com/src/components/layout/index.tsx create mode 100644 packages/fakeyou.com/src/hooks/useSearch/index.ts create mode 100644 packages/fakeyou.com/src/hooks/useSearch/useSearch.tsx diff --git a/packages/fakeyou.com/src/components/common/Button/Button.scss b/packages/fakeyou.com/src/components/common/Button/Button.scss index d5a58e8c67..2b77945926 100644 --- a/packages/fakeyou.com/src/components/common/Button/Button.scss +++ b/packages/fakeyou.com/src/components/common/Button/Button.scss @@ -3,13 +3,14 @@ .button { border-radius: 0.5rem; outline: none; - font-size: 15px; - font-weight: 500; + font-size: 15px !important; + font-weight: 500 !important; padding: 10px 20px; z-index: 2; display: flex; align-items: center; justify-content: center; + color: $white !important; } .button-primary, @@ -19,19 +20,19 @@ border: 2.5px solid; border-color: $primary; transition: 0.2s; - color: $white; + color: $white !important; } .button-primary:hover { background-color: lighten($primary, 5%); border-color: lighten($primary, 5%); - color: $white; + color: $white !important; } .button-secondary, .button-secondary:focus, .button-secondary:active { background-color: $secondary; - color: $white; + color: $white !important; border: 2.5px solid; border-color: $secondary; transition: 0.2s; @@ -39,7 +40,7 @@ .button-secondary:hover { background-color: lighten($secondary, 5%); - color: $white; + color: $white !important; border: 2.5px solid; border-color: lighten($secondary, 5%); } @@ -48,7 +49,7 @@ .button-destructive:focus, .button-destructive:active { background-color: $danger; - color: $white; + color: $white !important; border: 2.5px solid; border-color: $danger; transition: 0.2s; @@ -56,7 +57,7 @@ .button-destructive:hover { background-color: lighten($danger, 5%); - color: $white; + color: $white !important; border: 2.5px solid; border-color: lighten($danger, 5%); } @@ -65,7 +66,7 @@ .button-small:focus, .button-small:active { font-weight: 500; - font-size: 14px; + font-size: 14px !important; padding: 8.25px 16px; transition: 0.2s; border: none; diff --git a/packages/fakeyou.com/src/components/common/Button/Button.tsx b/packages/fakeyou.com/src/components/common/Button/Button.tsx index 188ca25bac..b67196aa13 100644 --- a/packages/fakeyou.com/src/components/common/Button/Button.tsx +++ b/packages/fakeyou.com/src/components/common/Button/Button.tsx @@ -1,4 +1,5 @@ import React, { ButtonHTMLAttributes } from "react"; +import { Link } from "react-router-dom"; import "./Button.scss"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; @@ -7,29 +8,68 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { label?: string; icon?: IconDefinition; small?: boolean; - secondary?: boolean; - danger?: boolean; + variant?: "primary" | "secondary" | "danger"; + to?: string; // for internal links + href?: string; // for external links + target?: "_blank" | "_self"; } export default function Button({ label, icon, small, - secondary, - danger, + variant = "primary", + to, + href, + target = "_self", ...rest }: ButtonProps) { - const buttonClasses = `button ${small ? "button-small" : ""} - ${ - secondary - ? "button-secondary" - : danger - ? "button-destructive" - : "button-primary" - } `; + let buttonClass = `button`; + if (small) { + buttonClass += ` button-small`; + } + + switch (variant) { + case "primary": + buttonClass += " button-primary"; + break; + case "secondary": + buttonClass += " button-secondary"; + break; + case "danger": + buttonClass += " button-destructive"; + break; + default: + buttonClass += " button-primary"; + break; + } + + if (to) { + return ( + <Link to={to} className={buttonClass}> + {icon && <FontAwesomeIcon icon={icon} className="me-2" />} + {label} + </Link> + ); + } + if (href) { + return ( + <a + href={href} + target={target} + rel="noopener noreferrer" + className={buttonClass} + > + {icon && <FontAwesomeIcon icon={icon} className="me-2" />} + {label} + </a> + ); + } + + // If neither 'to' nor 'href' are provided (regular button) return ( - <button className={buttonClasses} type="button" {...rest}> + <button className={buttonClass} type="button" {...rest}> {icon && <FontAwesomeIcon icon={icon} className="me-2" />} {label} </button> diff --git a/packages/fakeyou.com/src/components/common/Button/index.tsx b/packages/fakeyou.com/src/components/common/Button/index.tsx new file mode 100644 index 0000000000..c4719be7c0 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Button/index.tsx @@ -0,0 +1 @@ +export { default } from "./Button"; diff --git a/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.scss b/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.scss new file mode 100644 index 0000000000..f75c658315 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.scss @@ -0,0 +1,39 @@ +@import "scss/colours.scss"; + +.checkable-tag { + font-weight: 500; + border-radius: 0.5rem; + font-size: 13px; + padding: 9px 12px; + background-color: $secondary; + color: $white; + cursor: pointer; + transition: 0.2s; + -moz-user-select: none; + -khtml-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + border: 2px solid $secondary; + + &.checked { + background-color: lighten($secondary, 10%) !important; + color: $white; + border: 2px solid $primary !important; + } + + .remove-icon { + align-items: center; + font-size: 14px; + transition: 0.2s; + } + + &:hover { + background-color: lighten($secondary, 5%); + border: 2px solid lighten($secondary, 5%); + } + + &:hover > .remove-icon { + color: $primary; + } +} diff --git a/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.tsx b/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.tsx new file mode 100644 index 0000000000..6de7495d0a --- /dev/null +++ b/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import "./CheckableTag.scss"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faXmark } from "@fortawesome/pro-solid-svg-icons"; + +interface Props { + tag: string; + isSelected: boolean; + onToggle: (tag: string) => void; +} + +export default function CheckableTag({ tag, isSelected, onToggle }: Props) { + return ( + <div + className={`d-flex align-items-center checkable-tag ${ + isSelected ? "checked" : "" + }`} + onClick={() => onToggle(tag)} + > + {tag} + {isSelected && ( + <FontAwesomeIcon icon={faXmark} className="ms-2 remove-icon" /> + )} + </div> + ); +} diff --git a/packages/fakeyou.com/src/components/common/CheckableTag/index.tsx b/packages/fakeyou.com/src/components/common/CheckableTag/index.tsx new file mode 100644 index 0000000000..877c50fb3c --- /dev/null +++ b/packages/fakeyou.com/src/components/common/CheckableTag/index.tsx @@ -0,0 +1 @@ +export { default } from "./CheckableTag"; diff --git a/packages/fakeyou.com/src/components/common/Input/Input.tsx b/packages/fakeyou.com/src/components/common/Input/Input.tsx new file mode 100644 index 0000000000..4697f07970 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Input/Input.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; + +interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> { + icon?: IconDefinition; + label?: string; + textArea?: boolean; +} + +export default function Input({ label, icon, textArea, ...rest }: InputProps) { + return ( + <div> + {label && <label className="sub-title">{label}</label>} + + <div className={`form-group ${icon ? "input-icon" : ""}`}> + {icon && ( + <FontAwesomeIcon icon={icon} className="form-control-feedback" /> + )} + <input className="form-control" {...rest} /> + </div> + </div> + ); +} diff --git a/packages/fakeyou.com/src/components/common/Input/index.tsx b/packages/fakeyou.com/src/components/common/Input/index.tsx new file mode 100644 index 0000000000..a50d7d110e --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Input/index.tsx @@ -0,0 +1 @@ +export { default } from "./Input"; diff --git a/packages/fakeyou.com/src/components/common/ModelSearch/ModelSearch.tsx b/packages/fakeyou.com/src/components/common/ModelSearch/ModelSearch.tsx new file mode 100644 index 0000000000..58c00308f0 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ModelSearch/ModelSearch.tsx @@ -0,0 +1,20 @@ +import React from "react"; +import Input from "../Input"; +import { faSearch } from "@fortawesome/pro-solid-svg-icons"; + +interface Props { + value: string; + onChange: (value: string) => void; +} + +export default function ModelSearch({ value, onChange }: Props) { + return ( + <Input + icon={faSearch} + type="text" + value={value} + onChange={(e) => onChange(e.target.value)} + placeholder="Search..." + /> + ); +} diff --git a/packages/fakeyou.com/src/components/common/ModelSearch/dummyData.ts b/packages/fakeyou.com/src/components/common/ModelSearch/dummyData.ts new file mode 100644 index 0000000000..236d5c8acb --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ModelSearch/dummyData.ts @@ -0,0 +1,4 @@ +export const dummyData = [ + { id: 1, name: "Item 1", tags: ["tag1", "tag2"] }, + { id: 2, name: "Item 2", tags: ["tag2", "tag3"] }, +]; diff --git a/packages/fakeyou.com/src/components/common/ModelSearch/index.tsx b/packages/fakeyou.com/src/components/common/ModelSearch/index.tsx new file mode 100644 index 0000000000..e557975288 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ModelSearch/index.tsx @@ -0,0 +1 @@ +export { default } from "./ModelSearch"; diff --git a/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss b/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss new file mode 100644 index 0000000000..3a931215d3 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss @@ -0,0 +1,29 @@ +@import "scss/colours.scss"; + +.model-search-results { + background-color: lighten($panel, 6%); + border-radius: 0.5rem; + border: 1px solid lighten($panel, 12%); + + .type-tag { + font-weight: 600; + border-radius: 0.4rem; + font-size: 13px; + padding: 4px 8px; + background-color: $secondary; + color: $white; + cursor: pointer; + transition: 0.2s; + -moz-user-select: none; + -khtml-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + height: 100%; + + &.tt2 { + color: #494ea9; + background-color: #c6c7e1; + } + } +} diff --git a/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.tsx b/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.tsx new file mode 100644 index 0000000000..d0670d0450 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.tsx @@ -0,0 +1,28 @@ +import React from "react"; +import "./ModelSearchResults.scss"; + +interface Props { + data: any[]; +} + +export default function ModelSearchResults({ data }: Props) { + return ( + <div className="row g-3"> + {data.map((item) => ( + <div className="col-12 col-lg-6"> + <div className="model-search-results p-3" key={item.id}> + <h5 className="fw-semibold mb-0">{item.name}</h5> + <p className="">by {item.creator}</p> + <span + className={`type-tag ${ + item.type === "Tacotron2" ? "tt2" : "tt2" + }`} + > + {item.type} + </span> + </div> + </div> + ))} + </div> + ); +} diff --git a/packages/fakeyou.com/src/components/common/ModelSearchResults/index.tsx b/packages/fakeyou.com/src/components/common/ModelSearchResults/index.tsx new file mode 100644 index 0000000000..e1326737cc --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ModelSearchResults/index.tsx @@ -0,0 +1 @@ +export { default } from "./ModelSearchResults"; diff --git a/packages/fakeyou.com/src/components/common/ModelTags/ModelTags.tsx b/packages/fakeyou.com/src/components/common/ModelTags/ModelTags.tsx new file mode 100644 index 0000000000..b2b464bd65 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ModelTags/ModelTags.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import CheckableTag from "../CheckableTag"; + +interface Props { + tags: string[]; + selectedTags: string[]; + onSelectTag: (tag: string) => void; +} + +export default function ModelTags({ tags, selectedTags, onSelectTag }: Props) { + return ( + <div className="d-flex gap-2 flex-wrap"> + {tags.map((tag) => ( + <CheckableTag + key={tag} + tag={tag} + isSelected={selectedTags.includes(tag)} + onToggle={onSelectTag} + /> + ))} + </div> + ); +} diff --git a/packages/fakeyou.com/src/components/common/ModelTags/index.tsx b/packages/fakeyou.com/src/components/common/ModelTags/index.tsx new file mode 100644 index 0000000000..1719f41058 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ModelTags/index.tsx @@ -0,0 +1 @@ +export { default } from "./ModelTags"; diff --git a/packages/fakeyou.com/src/components/common/Panel/index.tsx b/packages/fakeyou.com/src/components/common/Panel/index.tsx new file mode 100644 index 0000000000..76888ed957 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Panel/index.tsx @@ -0,0 +1 @@ +export { default } from "./Panel"; diff --git a/packages/fakeyou.com/src/components/common/Select/Select.scss b/packages/fakeyou.com/src/components/common/Select/Select.scss new file mode 100644 index 0000000000..2ffb214fb9 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Select/Select.scss @@ -0,0 +1,68 @@ +@import "scss/colours.scss"; + +.select__control { + &.select { + height: 48px; + border-width: 2px; + padding-left: 0.15rem; + padding-right: 0.15rem; + background-color: $input-dark; + border-radius: 0.5rem; + border-color: $input-dark !important; + box-shadow: none; + cursor: pointer; + + &.no-padding { + padding-left: 0.5rem; + } + + &:hover { + background-color: lighten($input-dark, 5%); + border-color: lighten($input-dark, 5%) !important; + } + + &.focused { + border-color: $primary !important; + } + + &.with-icon { + padding-left: 2rem; + } + + &.rounded-full { + border-radius: 50px; + } + } + + .select-option { + background-color: $input-dark; + cursor: pointer; + padding: 0.5rem 1rem; + + &:hover { + background-color: lighten($input-dark, 8%); + } + } + + .select-input, + .select-value { + color: $white; + } + + .select-container { + background: $input-dark; + margin-top: 6px; + padding: 0; + border-radius: 0.5rem; + z-index: 3; + } + + .select-separator { + width: 1px; + opacity: 0.3; + } + + .select-placeholder { + color: rgba($white, 0.5) !important; + } +} diff --git a/packages/fakeyou.com/src/components/common/Select/Select.tsx b/packages/fakeyou.com/src/components/common/Select/Select.tsx new file mode 100644 index 0000000000..a52c07f79a --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Select/Select.tsx @@ -0,0 +1,53 @@ +import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; +import "./Select.scss"; +import { + default as ReactSelect, + Props as ReactSelectProps, +} from "react-select"; + +interface SelectProps extends ReactSelectProps { + icon?: IconDefinition; + label?: string; + rounded?: boolean; +} + +export default function Select({ label, icon, rounded, ...rest }: SelectProps) { + const SelectFieldClass = { + control: (state: any) => + state.isFocused + ? `select focused ${icon && "with-icon"} ${rounded && "rounded-full"}` + : `select ${icon && "with-icon"} ${rounded && "rounded-full"}`, + option: (state: any) => + state.isFocused ? "select-option" : "select-option", + input: (state: any) => (state.isFocused ? "select-input" : "select-input"), + placeholder: (state: any) => + state.isFocused ? "select-placeholder" : "select-placeholder", + singleValue: (state: any) => + state.isFocused ? "select-value" : "select-value", + menu: (state: any) => + state.isFocused ? "select-container" : "select-container", + indicatorSeparator: (state: any) => + state.isFocused ? "select-separator" : "select-separator", + }; + + return ( + <div> + {label && <label className="sub-title">{label}</label>} + + <div className={`form-group ${icon ? "input-icon" : ""}`}> + {icon && ( + <FontAwesomeIcon icon={icon} className="form-control-feedback" /> + )} + <div className="w-100"> + <ReactSelect + classNamePrefix="select" + classNames={SelectFieldClass} + {...rest} + /> + </div> + </div> + </div> + ); +} diff --git a/packages/fakeyou.com/src/components/common/Select/index.tsx b/packages/fakeyou.com/src/components/common/Select/index.tsx new file mode 100644 index 0000000000..cd39325ed3 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Select/index.tsx @@ -0,0 +1 @@ +export { default } from "./Select"; diff --git a/packages/fakeyou.com/src/components/common/ShareButton/ShareButton.tsx b/packages/fakeyou.com/src/components/common/ShareButton/ShareButton.tsx index a5501655b7..ed1fe885d2 100644 --- a/packages/fakeyou.com/src/components/common/ShareButton/ShareButton.tsx +++ b/packages/fakeyou.com/src/components/common/ShareButton/ShareButton.tsx @@ -35,8 +35,8 @@ export default function ShareButton(props: ShareButtonProps) { <Button label="Share Link" icon={faLink} - secondary - small + variant="secondary" + small={true} onClick={copyToClipboard} /> </div> diff --git a/packages/fakeyou.com/src/components/common/TextArea/TextArea.tsx b/packages/fakeyou.com/src/components/common/TextArea/TextArea.tsx new file mode 100644 index 0000000000..d5fa949ea2 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/TextArea/TextArea.tsx @@ -0,0 +1,19 @@ +import React from "react"; + +interface TextAreaProps + extends React.TextareaHTMLAttributes<HTMLTextAreaElement> { + label?: string; + textArea?: boolean; +} + +export default function TextArea({ label, textArea, ...rest }: TextAreaProps) { + return ( + <div> + {label && <label className="sub-title">{label}</label>} + + <div className="form-group"> + <textarea className="form-control" {...rest} /> + </div> + </div> + ); +} diff --git a/packages/fakeyou.com/src/components/common/TextArea/index.tsx b/packages/fakeyou.com/src/components/common/TextArea/index.tsx new file mode 100644 index 0000000000..44b0efb3db --- /dev/null +++ b/packages/fakeyou.com/src/components/common/TextArea/index.tsx @@ -0,0 +1 @@ +export { default } from "./TextArea"; diff --git a/packages/fakeyou.com/src/components/layout/MobileMenu/MobileMenu.tsx b/packages/fakeyou.com/src/components/layout/MobileMenu/MobileMenu.tsx index 41ba5a8b90..05c166a4fc 100644 --- a/packages/fakeyou.com/src/components/layout/MobileMenu/MobileMenu.tsx +++ b/packages/fakeyou.com/src/components/layout/MobileMenu/MobileMenu.tsx @@ -43,7 +43,7 @@ export default function MobileMenu(props: MobileMenuProps) { icon={faUser} label="Profile" small - secondary + variant="secondary" onClick={() => history.push(url)} /> </> @@ -58,7 +58,7 @@ export default function MobileMenu(props: MobileMenuProps) { <Button label="Menu" icon={faBars} - secondary + variant="secondary" small onClick={handleMenuButtonClick} /> diff --git a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx index e28e3ddca2..96ee68fd9d 100644 --- a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx +++ b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx @@ -1,46 +1,59 @@ import React from "react"; +import Panel from "../../common/Panel"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; +import Button from "components/common/Button"; -interface Props { - childProps?: any; - titleIcon?: JSX.Element; - titleComponent?: React.ComponentType; - title?: string; - subText: string; - showButtons: boolean; - actionButtons?: JSX.Element; +interface PageHeaderProps { + titleIcon?: IconDefinition; + title: string; + subText: string | React.ReactNode; + full?: boolean; + showButton?: boolean; + extension?: React.ReactNode; + buttonLabel?: string; + buttonVariant?: "primary" | "secondary" | "danger"; + buttonTo?: string; } export default function PageHeader({ - actionButtons, - childProps, - showButtons, - subText, - titleComponent: Title, - title, titleIcon, -}: Props) { + title, + subText, + full, + showButton, + extension, + buttonLabel, + buttonVariant = "primary", + buttonTo, +}: PageHeaderProps) { + const icon = ( + <>{titleIcon && <FontAwesomeIcon icon={titleIcon} className="me-3" />}</> + ); + return ( - <div className="container-panel hero-section py-4"> - <div className="panel"> - <div className="p-3 py-4 p-md-4"> - {Title ? ( - <Title {...childProps} /> - ) : ( - <h1 className="fw-bold text-center text-md-start"> - {titleIcon} - {title} - </h1> - )} - <p className="text-center text-md-start pt-1">{subText}</p> - {showButtons && ( - <div className="d-flex flex-column flex-md-row gap-3 justify-content-center justify-content-md-start mt-4"> - {actionButtons} + <div className="pt-3 pb-4 pt-lg-4"> + <Panel padding full={full}> + <div className="d-flex flex-column gap-4"> + <div> + <div className="d-flex"> + <h2 className="fw-bold flex-grow-1"> + {icon} + {title} + </h2> + {showButton && ( + <Button + variant={buttonVariant} + label={buttonLabel} + to={buttonTo} + /> + )} </div> - )} + <p>{subText}</p> + </div> + {extension && <div>{extension}</div>} </div> - </div> + </Panel> </div> ); } - -// export default PageHeader; diff --git a/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx b/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx index 4332f6aa44..e2b1344da7 100644 --- a/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx +++ b/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx @@ -156,7 +156,7 @@ export default function SideNav(props: SideNavProps) { <Button label={t("loginButton")} small - secondary + variant="secondary" onClick={() => { history.push("/login"); handleNavLinkClick(); @@ -194,7 +194,7 @@ export default function SideNav(props: SideNavProps) { icon={faUser} label={t("profileButton")} small - secondary + variant="secondary" onClick={() => { history.push(url); handleNavLinkClick(); @@ -209,7 +209,7 @@ export default function SideNav(props: SideNavProps) { icon={faSignOutAlt} label={t("logOutButton")} small - danger + variant="danger" onClick={async () => { await logoutHandler(); handleNavLinkClick(); diff --git a/packages/fakeyou.com/src/components/layout/index.tsx b/packages/fakeyou.com/src/components/layout/index.tsx deleted file mode 100644 index 110b9fc1d6..0000000000 --- a/packages/fakeyou.com/src/components/layout/index.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import PageHeader from './PageHeader'; - -export { - PageHeader, -}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/hooks/useSearch/index.ts b/packages/fakeyou.com/src/hooks/useSearch/index.ts new file mode 100644 index 0000000000..54a7749ee4 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useSearch/index.ts @@ -0,0 +1 @@ +export { default } from "./useSearch"; diff --git a/packages/fakeyou.com/src/hooks/useSearch/useSearch.tsx b/packages/fakeyou.com/src/hooks/useSearch/useSearch.tsx new file mode 100644 index 0000000000..ebbf9c6a5e --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useSearch/useSearch.tsx @@ -0,0 +1,32 @@ +import { useState, useMemo } from "react"; + +export default function useSearch(initialData: any[]) { + const [searchTerm, setSearchTerm] = useState<string>(""); + const [selectedTags, setSelectedTags] = useState<string[]>([]); + + const filteredData = useMemo(() => { + let tempData = [...initialData]; + + if (searchTerm) { + tempData = tempData.filter((item) => + item.name.toLowerCase().includes(searchTerm.toLowerCase()) + ); + } + + if (selectedTags.length) { + tempData = tempData.filter((item) => + selectedTags.every((tag) => item.tags.includes(tag)) + ); + } + + return tempData; + }, [searchTerm, selectedTags, initialData]); + + return { + searchTerm, + setSearchTerm, + selectedTags, + setSelectedTags, + filteredData, + }; +} diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index 697a1909c3..3aa2e4c4c8 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -782,7 +782,7 @@ styles with important tags: } .select-placeholder { - color: $white !important; + color: $white; } .select-container { diff --git a/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx b/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx index be8cd4b328..874d2e5c0b 100644 --- a/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx @@ -1,17 +1,91 @@ import React from "react"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; import Container from "components/common/Container"; -import Panel from "components/common/Panel/Panel"; +import PageHeader from "components/layout/PageHeader"; +import { faMessageDots } from "@fortawesome/pro-solid-svg-icons"; +import ModelSearch from "components/common/ModelSearch"; +import Panel from "components/common/Panel"; +import useSearch from "hooks/useSearch/useSearch"; +import ModelSearchResults from "components/common/ModelSearchResults"; +import ModelTags from "components/common/ModelTags"; interface TtsModelSearchPageProps { sessionWrapper: SessionWrapper; } +const dummyData = [ + { + id: 1, + name: "Spongebob", + tags: ["English", "High-pitched", "Character"], + type: "Tacotron2", + }, + { + id: 2, + name: "Mariano Closs", + tags: ["Spanish", "Low-pitched"], + type: "Tacotron2", + }, + { + id: 3, + name: "Cristiano Ronaldo", + tags: ["Portuguese", "Low-pitched"], + type: "Tacotron2", + }, +]; + +const allTags = [ + "English", + "Spanish", + "Portuguese", + "High-pitched", + "Low-pitched", + "Character", +]; + export default function TtsModelSearchPage(props: TtsModelSearchPageProps) { + const { + searchTerm, + setSearchTerm, + selectedTags, + setSelectedTags, + filteredData, + } = useSearch(dummyData); + + const handleSelectTag = (tag: string) => { + setSelectedTags((prev) => { + if (prev.includes(tag)) { + return prev.filter((t) => t !== tag); + } + return [...prev, tag]; + }); + }; + + const searchTts = ( + <div className="d-flex flex-column gap-3"> + <ModelSearch value={searchTerm} onChange={setSearchTerm} /> + <ModelTags + tags={allTags} + selectedTags={selectedTags} + onSelectTag={handleSelectTag} + /> + </div> + ); + return ( <Container type="panel"> + <PageHeader + title="Text to Speech" + titleIcon={faMessageDots} + subText="Turn text into your favorite character's speaking voice." + showButton={true} + buttonLabel="Create a voice" + buttonVariant="secondary" + buttonTo="/voice-designer" + extension={searchTts} + /> <Panel padding={true}> - <div>test</div> + <ModelSearchResults data={filteredData} /> </Panel> </Container> ); From a65267ec7f93dbdfbf94bd23918aa2e66e541244 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 13 Oct 2023 00:40:22 +0700 Subject: [PATCH 04/51] updates --- .../common/CheckableTag/CheckableTag.scss | 2 +- .../common/CheckableTag/CheckableTag.tsx | 8 +- .../common/ModelSearch/ModelSearch.tsx | 4 +- .../common/ModelSearch/dummyData.ts | 4 - .../ModelSearchResults.scss | 14 +++- .../ModelSearchResults/ModelSearchResults.tsx | 75 +++++++++++++++---- .../components/common/ModelTags/ModelTags.tsx | 8 +- .../layout/PageHeader/PageHeader.tsx | 16 ++-- .../src/hooks/useShortenNumber/index.ts | 1 + .../useShortenNumber/useShortenNumber.tsx | 6 ++ .../tts_model_search/TtsModelSearchPage.tsx | 41 +++++++++- 11 files changed, 141 insertions(+), 38 deletions(-) delete mode 100644 packages/fakeyou.com/src/components/common/ModelSearch/dummyData.ts create mode 100644 packages/fakeyou.com/src/hooks/useShortenNumber/index.ts create mode 100644 packages/fakeyou.com/src/hooks/useShortenNumber/useShortenNumber.tsx diff --git a/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.scss b/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.scss index f75c658315..8274c937bf 100644 --- a/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.scss +++ b/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.scss @@ -4,7 +4,7 @@ font-weight: 500; border-radius: 0.5rem; font-size: 13px; - padding: 9px 12px; + padding: 6px 12px; background-color: $secondary; color: $white; cursor: pointer; diff --git a/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.tsx b/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.tsx index 6de7495d0a..6e07d0e74d 100644 --- a/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.tsx +++ b/packages/fakeyou.com/src/components/common/CheckableTag/CheckableTag.tsx @@ -3,13 +3,17 @@ import "./CheckableTag.scss"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faXmark } from "@fortawesome/pro-solid-svg-icons"; -interface Props { +interface CheckableTagProps { tag: string; isSelected: boolean; onToggle: (tag: string) => void; } -export default function CheckableTag({ tag, isSelected, onToggle }: Props) { +export default function CheckableTag({ + tag, + isSelected, + onToggle, +}: CheckableTagProps) { return ( <div className={`d-flex align-items-center checkable-tag ${ diff --git a/packages/fakeyou.com/src/components/common/ModelSearch/ModelSearch.tsx b/packages/fakeyou.com/src/components/common/ModelSearch/ModelSearch.tsx index 58c00308f0..7b84ad5f0c 100644 --- a/packages/fakeyou.com/src/components/common/ModelSearch/ModelSearch.tsx +++ b/packages/fakeyou.com/src/components/common/ModelSearch/ModelSearch.tsx @@ -2,12 +2,12 @@ import React from "react"; import Input from "../Input"; import { faSearch } from "@fortawesome/pro-solid-svg-icons"; -interface Props { +interface ModelSearchProps { value: string; onChange: (value: string) => void; } -export default function ModelSearch({ value, onChange }: Props) { +export default function ModelSearch({ value, onChange }: ModelSearchProps) { return ( <Input icon={faSearch} diff --git a/packages/fakeyou.com/src/components/common/ModelSearch/dummyData.ts b/packages/fakeyou.com/src/components/common/ModelSearch/dummyData.ts deleted file mode 100644 index 236d5c8acb..0000000000 --- a/packages/fakeyou.com/src/components/common/ModelSearch/dummyData.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const dummyData = [ - { id: 1, name: "Item 1", tags: ["tag1", "tag2"] }, - { id: 2, name: "Item 2", tags: ["tag2", "tag3"] }, -]; diff --git a/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss b/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss index 3a931215d3..6c4c355bbd 100644 --- a/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss +++ b/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss @@ -5,14 +5,20 @@ border-radius: 0.5rem; border: 1px solid lighten($panel, 12%); + .creator-name { + font-weight: 400; + font-size: 14px; + color: $white; + margin-bottom: 0.5rem; + } + .type-tag { font-weight: 600; - border-radius: 0.4rem; + border-radius: 0.35rem; font-size: 13px; padding: 4px 8px; background-color: $secondary; color: $white; - cursor: pointer; transition: 0.2s; -moz-user-select: none; -khtml-user-select: none; @@ -26,4 +32,8 @@ background-color: #c6c7e1; } } + + .model-details { + font-size: 14px; + } } diff --git a/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.tsx b/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.tsx index d0670d0450..65f808499a 100644 --- a/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.tsx +++ b/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.tsx @@ -1,28 +1,71 @@ import React from "react"; import "./ModelSearchResults.scss"; +import { Link } from "react-router-dom"; +import Button from "../Button"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faChartSimple, + faComment, + faHeart, +} from "@fortawesome/pro-solid-svg-icons"; -interface Props { +interface ModelSearchResultsProps { data: any[]; } -export default function ModelSearchResults({ data }: Props) { +function shortenNumber(num: number): string { + if (Math.abs(num) < 1e3) return num.toString(); + if (Math.abs(num) < 1e6) return (num / 1e3).toFixed(1) + "k"; + if (Math.abs(num) < 1e9) return (num / 1e6).toFixed(1) + "M"; + return num.toString(); +} + +export default function ModelSearchResults({ data }: ModelSearchResultsProps) { return ( <div className="row g-3"> - {data.map((item) => ( - <div className="col-12 col-lg-6"> - <div className="model-search-results p-3" key={item.id}> - <h5 className="fw-semibold mb-0">{item.name}</h5> - <p className="">by {item.creator}</p> - <span - className={`type-tag ${ - item.type === "Tacotron2" ? "tt2" : "tt2" - }`} - > - {item.type} - </span> + {data.map((item) => { + return ( + <div className="col-12 col-lg-6" key={item.id}> + <div className="model-search-results p-3"> + <h5 className="fw-semibold mb-0">{item.name}</h5> + <p className="creator-name"> + by{" "} + <Link className="fw-medium" to={`/profile/${item.creator}`}> + {item.creator} + </Link> + </p> + <div className="d-flex align-items-end"> + <div className="flex-grow-1"> + <span + className={`type-tag ${ + item.type === "Tacotron2" ? "tt2" : "tt2" + }`} + > + {item.type} + </span> + <div className="d-flex gap-3 model-details fw-medium mt-3"> + <div> + <FontAwesomeIcon icon={faHeart} className="me-2" /> + {item.likes && shortenNumber(item.likes)} + </div> + <div> + <FontAwesomeIcon icon={faChartSimple} className="me-2" /> + {item.uses && shortenNumber(item.uses)} + </div> + <div> + <FontAwesomeIcon icon={faComment} className="me-2" /> + {item.comments && shortenNumber(item.comments)} + </div> + </div> + </div> + <div> + <Button label="Use Voice" small={true} to="/" /> + </div> + </div> + </div> </div> - </div> - ))} + ); + })} </div> ); } diff --git a/packages/fakeyou.com/src/components/common/ModelTags/ModelTags.tsx b/packages/fakeyou.com/src/components/common/ModelTags/ModelTags.tsx index b2b464bd65..474334e460 100644 --- a/packages/fakeyou.com/src/components/common/ModelTags/ModelTags.tsx +++ b/packages/fakeyou.com/src/components/common/ModelTags/ModelTags.tsx @@ -1,13 +1,17 @@ import React from "react"; import CheckableTag from "../CheckableTag"; -interface Props { +interface ModelTagsProps { tags: string[]; selectedTags: string[]; onSelectTag: (tag: string) => void; } -export default function ModelTags({ tags, selectedTags, onSelectTag }: Props) { +export default function ModelTags({ + tags, + selectedTags, + onSelectTag, +}: ModelTagsProps) { return ( <div className="d-flex gap-2 flex-wrap"> {tags.map((tag) => ( diff --git a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx index 96ee68fd9d..62682ba82d 100644 --- a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx +++ b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx @@ -41,13 +41,15 @@ export default function PageHeader({ {icon} {title} </h2> - {showButton && ( - <Button - variant={buttonVariant} - label={buttonLabel} - to={buttonTo} - /> - )} + <div className="d-none d-md-block"> + {showButton && ( + <Button + variant={buttonVariant} + label={buttonLabel} + to={buttonTo} + /> + )} + </div> </div> <p>{subText}</p> </div> diff --git a/packages/fakeyou.com/src/hooks/useShortenNumber/index.ts b/packages/fakeyou.com/src/hooks/useShortenNumber/index.ts new file mode 100644 index 0000000000..393d617cc0 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useShortenNumber/index.ts @@ -0,0 +1 @@ +export { default } from "./useShortenNumber"; diff --git a/packages/fakeyou.com/src/hooks/useShortenNumber/useShortenNumber.tsx b/packages/fakeyou.com/src/hooks/useShortenNumber/useShortenNumber.tsx new file mode 100644 index 0000000000..cc24407c9a --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useShortenNumber/useShortenNumber.tsx @@ -0,0 +1,6 @@ +export default function useShortenNumber(num: number): string { + if (Math.abs(num) < 1e3) return num.toString(); + if (Math.abs(num) < 1e6) return (num / 1e3).toFixed(1) + "k"; + if (Math.abs(num) < 1e9) return (num / 1e6).toFixed(1) + "M"; + return num.toString(); +} diff --git a/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx b/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx index 874d2e5c0b..9989fd83be 100644 --- a/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx @@ -2,12 +2,13 @@ import React from "react"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; import Container from "components/common/Container"; import PageHeader from "components/layout/PageHeader"; -import { faMessageDots } from "@fortawesome/pro-solid-svg-icons"; +import { faClock, faMessageDots } from "@fortawesome/pro-solid-svg-icons"; import ModelSearch from "components/common/ModelSearch"; import Panel from "components/common/Panel"; import useSearch from "hooks/useSearch/useSearch"; import ModelSearchResults from "components/common/ModelSearchResults"; import ModelTags from "components/common/ModelTags"; +import Select from "components/common/Select"; interface TtsModelSearchPageProps { sessionWrapper: SessionWrapper; @@ -19,18 +20,33 @@ const dummyData = [ name: "Spongebob", tags: ["English", "High-pitched", "Character"], type: "Tacotron2", + creator: "echelon", + likes: 14000, + uses: 1000000, + comments: 250, + time: new Date("2023-09-20T12:00:00Z").toISOString(), }, { id: 2, name: "Mariano Closs", tags: ["Spanish", "Low-pitched"], type: "Tacotron2", + creator: "echelon", + likes: 308290, + uses: 30000000, + comments: 1200, + time: new Date("2023-10-12T12:00:00Z").toISOString(), }, { id: 3, name: "Cristiano Ronaldo", tags: ["Portuguese", "Low-pitched"], type: "Tacotron2", + creator: "echelon", + likes: 17500, + uses: 40000000, + comments: 250, + time: new Date("2023-09-20T12:00:00Z").toISOString(), }, ]; @@ -72,12 +88,24 @@ export default function TtsModelSearchPage(props: TtsModelSearchPageProps) { </div> ); + const sortOptions = [ + { value: "most liked", label: "Most Liked" }, + { value: "most used", label: "Most Used" }, + { value: "moset recent", label: "Most Recent" }, + ]; + const sortTimeOptions = [ + { value: "all time", label: "All Time" }, + { value: "today", label: "Today" }, + { value: "this week", label: "This Week" }, + { value: "this month", label: "This Month" }, + ]; + return ( <Container type="panel"> <PageHeader title="Text to Speech" titleIcon={faMessageDots} - subText="Turn text into your favorite character's speaking voice." + subText="Turn text into your favorite character's voice." showButton={true} buttonLabel="Create a voice" buttonVariant="secondary" @@ -85,6 +113,15 @@ export default function TtsModelSearchPage(props: TtsModelSearchPageProps) { extension={searchTts} /> <Panel padding={true}> + <div className="d-flex gap-2 mb-3"> + <Select options={sortOptions} defaultValue={sortOptions[0]} /> + <Select + icon={faClock} + options={sortTimeOptions} + defaultValue={sortTimeOptions[0]} + /> + </div> + <ModelSearchResults data={filteredData} /> </Panel> </Container> From 8cc9b57abf0b38bb6923e0a530311760174c9945 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 13 Oct 2023 00:44:42 +0700 Subject: [PATCH 05/51] added more dummy data --- .../tts_model_search/TtsModelSearchPage.tsx | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx b/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx index 9989fd83be..c221b84d32 100644 --- a/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx @@ -48,6 +48,39 @@ const dummyData = [ comments: 250, time: new Date("2023-09-20T12:00:00Z").toISOString(), }, + { + id: 4, + name: "Messi", + tags: ["Portuguese", "Low-pitched"], + type: "Tacotron2", + creator: "echelon", + likes: 17500, + uses: 40000000, + comments: 250, + time: new Date("2023-09-20T12:00:00Z").toISOString(), + }, + { + id: 5, + name: "Morty", + tags: ["English", "High-pitched", "Character"], + type: "Tacotron2", + creator: "echelon", + likes: 14000, + uses: 1000000, + comments: 250, + time: new Date("2023-09-20T12:00:00Z").toISOString(), + }, + { + id: 6, + name: "Bad Bunny", + tags: ["Spanish", "Low-pitched"], + type: "Tacotron2", + creator: "echelon", + likes: 308290, + uses: 30000000, + comments: 1200, + time: new Date("2023-10-12T12:00:00Z").toISOString(), + }, ]; const allTags = [ From 3050c66a98841a4d25e22545e619476bfccd2534 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 13 Oct 2023 00:59:14 +0700 Subject: [PATCH 06/51] minor updates --- .../ModelSearchResults/ModelSearchResults.scss | 1 + .../src/components/common/Select/Select.scss | 4 ++++ .../src/components/common/Select/Select.tsx | 15 +++++++++++++-- .../tts/tts_model_search/TtsModelSearchPage.tsx | 9 +++++++-- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss b/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss index 6c4c355bbd..0105a9fc09 100644 --- a/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss +++ b/packages/fakeyou.com/src/components/common/ModelSearchResults/ModelSearchResults.scss @@ -34,6 +34,7 @@ } .model-details { + color: rgba($white, 0.8); font-size: 14px; } } diff --git a/packages/fakeyou.com/src/components/common/Select/Select.scss b/packages/fakeyou.com/src/components/common/Select/Select.scss index 2ffb214fb9..325d4a91cf 100644 --- a/packages/fakeyou.com/src/components/common/Select/Select.scss +++ b/packages/fakeyou.com/src/components/common/Select/Select.scss @@ -66,3 +66,7 @@ color: rgba($white, 0.5) !important; } } + +.select-small { + font-size: 14px !important; +} diff --git a/packages/fakeyou.com/src/components/common/Select/Select.tsx b/packages/fakeyou.com/src/components/common/Select/Select.tsx index a52c07f79a..7f1e44e8a7 100644 --- a/packages/fakeyou.com/src/components/common/Select/Select.tsx +++ b/packages/fakeyou.com/src/components/common/Select/Select.tsx @@ -11,9 +11,16 @@ interface SelectProps extends ReactSelectProps { icon?: IconDefinition; label?: string; rounded?: boolean; + small?: boolean; } -export default function Select({ label, icon, rounded, ...rest }: SelectProps) { +export default function Select({ + label, + icon, + rounded, + small, + ...rest +}: SelectProps) { const SelectFieldClass = { control: (state: any) => state.isFocused @@ -36,7 +43,11 @@ export default function Select({ label, icon, rounded, ...rest }: SelectProps) { <div> {label && <label className="sub-title">{label}</label>} - <div className={`form-group ${icon ? "input-icon" : ""}`}> + <div + className={`form-group ${icon ? "input-icon" : ""} ${ + small && "select-small" + }`} + > {icon && ( <FontAwesomeIcon icon={icon} className="form-control-feedback" /> )} diff --git a/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx b/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx index c221b84d32..10da0cb594 100644 --- a/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/tts/tts_model_search/TtsModelSearchPage.tsx @@ -146,9 +146,14 @@ export default function TtsModelSearchPage(props: TtsModelSearchPageProps) { extension={searchTts} /> <Panel padding={true}> - <div className="d-flex gap-2 mb-3"> - <Select options={sortOptions} defaultValue={sortOptions[0]} /> + <div className="d-flex gap-2 mb-4"> <Select + small={true} + options={sortOptions} + defaultValue={sortOptions[0]} + /> + <Select + small={true} icon={faClock} options={sortTimeOptions} defaultValue={sortTimeOptions[0]} From d91869bf0c69bdb23a921ea767d32534dd4e29b6 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 13 Oct 2023 11:12:19 +0700 Subject: [PATCH 07/51] remove all video lipsync (w2l) links --- .../pages/contribute/ContributeIndexPage.tsx | 14 +----------- .../src/v2/view/pages/landing/LandingPage.tsx | 22 +------------------ 2 files changed, 2 insertions(+), 34 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/contribute/ContributeIndexPage.tsx b/packages/fakeyou.com/src/v2/view/pages/contribute/ContributeIndexPage.tsx index 78721171c2..19a424579c 100644 --- a/packages/fakeyou.com/src/v2/view/pages/contribute/ContributeIndexPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/contribute/ContributeIndexPage.tsx @@ -118,18 +118,6 @@ function ContributeIndexPage(props: Props) { Upload Vocoder </Link> </div> - <div className="col-12 col-md-6"> - <Link to="/upload/w2l_video" className="btn btn-primary w-100"> - <FontAwesomeIcon icon={faVideo} className="me-3" /> - {t("pages.contributeIndex.buttonUploadW2lVideo")} - </Link> - </div> - <div className="col-12 col-md-6"> - <Link to="/upload/w2l_photo" className="btn btn-primary w-100"> - <FontAwesomeIcon icon={faImage} className="me-3" /> - {t("pages.contributeIndex.buttonUploadW2lPhoto")} - </Link> - </div> </div> </div> </div> @@ -156,7 +144,7 @@ function ContributeIndexPage(props: Props) { </div> </div> </div> - <div className="container-panel pt-3"> + <div className="container-panel pt-3 pb-5"> <div className="panel p-3 py-4 p-md-4 text-center text-lg-start"> <h2 className="fw-bold"> <FontAwesomeIcon icon={faHandsHelping} className="me-3" /> diff --git a/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx b/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx index a9f2176041..c49ff45d32 100644 --- a/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx @@ -328,30 +328,10 @@ function LandingPage(props: Props) { <img className="img-fluid" src="/images/landing/select-w2l.webp" - alt="Video Lip Sync" + alt="Face Animator" /> </Link> </div> - <div className="col-12 col-md-4"> - <Link - to="/video" - className="panel panel-select d-flex flex-column align-items-center h-auto pb-4" - > - <div className="d-flex px-4 pt-4 align-items-center w-100"> - <div className="flex-grow-1"> - <h3 className="fw-bold text-white mb-1"> - {t("productVideoTitle")} - </h3> - <h6 className="fw-normal opacity-75 text-white mb-0"> - {t("productVideoText")} - </h6> - </div> - <Link to="/video" className="btn btn-square mt-1"> - <FontAwesomeIcon icon={faArrowRight} /> - </Link> - </div> - </Link> - </div> <img src="/images/landing/bg-dots.webp" alt="background dots" From e3e088fa8076e91e2b3ed79bbf97f92a0fcc6af5 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 13 Oct 2023 11:32:59 +0700 Subject: [PATCH 08/51] remove unused imports --- .../src/v2/view/pages/contribute/ContributeIndexPage.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/contribute/ContributeIndexPage.tsx b/packages/fakeyou.com/src/v2/view/pages/contribute/ContributeIndexPage.tsx index 19a424579c..9ec39a81c6 100644 --- a/packages/fakeyou.com/src/v2/view/pages/contribute/ContributeIndexPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/contribute/ContributeIndexPage.tsx @@ -8,8 +8,6 @@ import { Trans } from "react-i18next"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faVolumeHigh, - faVideo, - faImage, faTags, faHandsHelping, } from "@fortawesome/free-solid-svg-icons"; From b03faf22c4940e3c8f51292800b387e0bff8f698 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 13 Oct 2023 11:46:11 +0700 Subject: [PATCH 09/51] face animator document title and link change --- _redirects | 2 +- .../src/components/layout/SideNav/SideNav.tsx | 2 +- .../fakeyou.com/src/v2/view/PageContainer.tsx | 2 +- .../fakeyou.com/src/v2/view/nav/FooterNav.tsx | 2 +- .../fakeyou.com/src/v2/view/nav/TopNav.tsx | 2 +- .../src/v2/view/pages/landing/LandingPage.tsx | 6 +-- .../lipsync/LipsyncEditor/LipsyncEditor.tsx | 43 +++++++++++-------- 7 files changed, 34 insertions(+), 25 deletions(-) diff --git a/_redirects b/_redirects index f137d71658..4eaed148ed 100644 --- a/_redirects +++ b/_redirects @@ -10,7 +10,7 @@ /coming-soon* /index.html 200 /commissions* /index.html 200 /contribute* /index.html 200 -/face-animation* /index.html 200 +/face-animator* /index.html 200 /firehose* /index.html 200 /guide* /index.html 200 /jobs* /index.html 200 diff --git a/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx b/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx index e2b1344da7..55514c2d0a 100644 --- a/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx +++ b/packages/fakeyou.com/src/components/layout/SideNav/SideNav.tsx @@ -271,7 +271,7 @@ export default function SideNav(props: SideNavProps) { <li className="sidebar-heading">{t("videoTitle")}</li> <li> <NavLink - to="/face-animation" + to="/face-animator" activeClassName="active-link" onClick={handleNavLinkClick} > diff --git a/packages/fakeyou.com/src/v2/view/PageContainer.tsx b/packages/fakeyou.com/src/v2/view/PageContainer.tsx index 537ed1e29f..6c1298ee8e 100644 --- a/packages/fakeyou.com/src/v2/view/PageContainer.tsx +++ b/packages/fakeyou.com/src/v2/view/PageContainer.tsx @@ -595,7 +595,7 @@ class PageContainer extends React.Component< /> </Route> - <Route path="/face-animation"> + <Route path="/face-animator"> <LipsyncEditor {...{ enqueueInferenceJob: this.props.enqueueInferenceJob, diff --git a/packages/fakeyou.com/src/v2/view/nav/FooterNav.tsx b/packages/fakeyou.com/src/v2/view/nav/FooterNav.tsx index fccd49b048..ac4309b6b4 100644 --- a/packages/fakeyou.com/src/v2/view/nav/FooterNav.tsx +++ b/packages/fakeyou.com/src/v2/view/nav/FooterNav.tsx @@ -214,7 +214,7 @@ function FooterNav(props: Props) { </li> <li> - <Link to="/face-animation">{t("productFaceAnimator")}</Link> + <Link to="/face-animator">{t("productFaceAnimator")}</Link> </li> <li> diff --git a/packages/fakeyou.com/src/v2/view/nav/TopNav.tsx b/packages/fakeyou.com/src/v2/view/nav/TopNav.tsx index e5dd48d3ac..f69bb2c789 100644 --- a/packages/fakeyou.com/src/v2/view/nav/TopNav.tsx +++ b/packages/fakeyou.com/src/v2/view/nav/TopNav.tsx @@ -245,7 +245,7 @@ function TopNav(props: Props) { </Link> </li> <li data-bs-toggle="offcanvas"> - <Link className="dropdown-item" to="/face-animation"> + <Link className="dropdown-item" to="/face-animator"> <FontAwesomeIcon icon={faFaceViewfinder} className="me-2" diff --git a/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx b/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx index c49ff45d32..b048c6a5ac 100644 --- a/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/landing/LandingPage.tsx @@ -156,7 +156,7 @@ function LandingPage(props: Props) { icon={faSparkles} message="Have you tried our new Face Animator? Turn photos of faces into animated lip-synced videos with just a picture and some audio!" alertVariant="new" - link="/face-animation" + link="/face-animator" linkText="Try it now" /> @@ -300,7 +300,7 @@ function LandingPage(props: Props) { </div> <div className="col-12 col-md-4"> <Link - to="/face-animation" + to="/face-animator" className="panel panel-select d-flex flex-column align-items-center" > <div className="d-flex px-4 pt-4 align-items-start w-100"> @@ -320,7 +320,7 @@ function LandingPage(props: Props) { {t("productFaceAnimatorText")} </h6> </div> - <Link to="/face-animation" className="btn btn-square mt-1"> + <Link to="/face-animator" className="btn btn-square mt-1"> <FontAwesomeIcon icon={faArrowRight} /> </Link> </div> diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.tsx b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.tsx index daf0ea63d9..37d7f8611c 100644 --- a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.tsx @@ -19,13 +19,14 @@ import { // EnqueueFaceAnimationRequest, } from "@storyteller/components/src/api/face_animation/EnqueueFaceAnimation"; import FaceAnimatorTitle from "./FaceAnimatorTitle"; -import FaceAnimatorInput from './FaceAnimatorInput'; -import FaceAnimatorWorking from './FaceAnimatorWorking'; +import FaceAnimatorInput from "./FaceAnimatorInput"; +import FaceAnimatorWorking from "./FaceAnimatorWorking"; import FaceAnimatorSuccess from "./FaceAnimatorSuccess"; import { FaceAnimatorCore } from "./FaceAnimatorTypes"; import { BasicVideo } from "components/common"; import "./LipsyncEditor.scss"; import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob"; +import { usePrefixedDocumentTitle } from "common/UsePrefixedDocumentTitle"; export default function LipsyncEditor({ enqueueInferenceJob, @@ -34,6 +35,7 @@ export default function LipsyncEditor({ ...rest }: FaceAnimatorCore) { const { t } = useLocalize("FaceAnimator"); + usePrefixedDocumentTitle("AI Face Animator"); // the ready states are set by functions which run after the upload input animation is completed, which then illuminates the respective checkmark in a staggered way to draw attention to the workflow, and reduces concurrent animations @@ -46,23 +48,26 @@ export default function LipsyncEditor({ const [index, indexSet] = useState<number>(0); // index = slideshow slide position //const [animationStyle,animationStyleSet] = useState(0); - const [frameDimensions,frameDimensionsSet] = useState("twitter_square"); - const [removeWatermark,removeWatermarkSet] = useState(false); - const [disableFaceEnhancement,disableFaceEnhancementSet] = useState(false); - const [still,stillSet] = useState(false); + const [frameDimensions, frameDimensionsSet] = useState("twitter_square"); + const [removeWatermark, removeWatermarkSet] = useState(false); + const [disableFaceEnhancement, disableFaceEnhancementSet] = useState(false); + const [still, stillSet] = useState(false); //const animationChange = ({ target }: any) => animationStyleSet(target.value); - const frameDimensionsChange = ({ target }: any) => frameDimensionsSet(target.value); - const removeWatermarkChange = ({ target }: any) => removeWatermarkSet(target.checked); - const disableFaceEnhancementChange = ({ target }: any) => disableFaceEnhancementSet(target.checked); + const frameDimensionsChange = ({ target }: any) => + frameDimensionsSet(target.value); + const removeWatermarkChange = ({ target }: any) => + removeWatermarkSet(target.checked); + const disableFaceEnhancementChange = ({ target }: any) => + disableFaceEnhancementSet(target.checked); const stillChange = ({ target }: any) => stillSet(target.checked); - const clearInputs = () => { - //animationStyleSet(0); - stillSet(false); - frameDimensionsSet("twitter_square"); - removeWatermarkSet(false); + const clearInputs = () => { + //animationStyleSet(0); + stillSet(false); + frameDimensionsSet("twitter_square"); + removeWatermarkSet(false); disableFaceEnhancementSet(false); - } + }; const makeRequest = (mode: number) => ({ uuid_idempotency_token: uuidv4(), @@ -144,7 +149,11 @@ export default function LipsyncEditor({ <div {...{ className: "panel lipsync-panel p-3 py-4 p-md-4" }}> <FaceAnimatorTitle {...headerProps} /> {transitions((style, i) => { - const Page = [FaceAnimatorInput, FaceAnimatorWorking, FaceAnimatorSuccess][page]; + const Page = [ + FaceAnimatorInput, + FaceAnimatorWorking, + FaceAnimatorSuccess, + ][page]; return Page ? ( <Page {...{ @@ -173,7 +182,7 @@ export default function LipsyncEditor({ })} </div> <div {...{ className: "face-animator-mobile-sample" }}> - <BasicVideo {...{ src: "/videos/face-animator-instruction-en.mp4" }}/> + <BasicVideo {...{ src: "/videos/face-animator-instruction-en.mp4" }} /> </div> </div> ); From 43bcbd8fa10a2dbfaa981b760bd2e3c7eca71e97 Mon Sep 17 00:00:00 2001 From: Brandon Thomas <echelon@gmail.com> Date: Fri, 13 Oct 2023 00:58:20 -0400 Subject: [PATCH 10/51] redirect old face-animation URL --- _redirects | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_redirects b/_redirects index 4eaed148ed..2c2c0c7c3b 100644 --- a/_redirects +++ b/_redirects @@ -40,6 +40,10 @@ /video* /index.html 200 /voice-conversion* /index.html 200 /w2l* /index.html 200 + +# Old paths +/face-animation* /face-animator 302 + # This is for YCombinator. # This is the *OLD* video for Summer 2022. We'll re-edit. # PLEASE DO NOT ACECSS THIS URL OR WATCH. IT WILL CHANGE THE From 7177cb760ad8b22bf18a07b93f187ed9ab473490 Mon Sep 17 00:00:00 2001 From: olivicmic <vic@vics.pics> Date: Fri, 13 Oct 2023 14:47:12 -0700 Subject: [PATCH 11/51] added job status section to face animator and corresponding modules --- packages/fakeyou.com/src/App.tsx | 4 + .../providers/InferenceJobs/InferenceJobs.tsx | 27 ++++ .../providers/InferenceJobs/index.ts | 1 + .../src/components/providers/index.ts | 3 + .../src/context/InferenceJobsContext.tsx | 31 +++++ packages/fakeyou.com/src/context/index.ts | 3 + packages/fakeyou.com/src/hooks/index.tsx | 3 +- .../src/hooks/useInferenceJobs/index.ts | 1 + .../useInferenceJobs/useInferenceJobs.tsx | 22 ++++ .../LipsyncEditor/FaceAnimatorJobs.tsx | 91 ++++++++++++++ .../LipsyncEditor/FaceAnimatorSuccess.tsx | 87 ++----------- .../LipsyncEditor/FaceAnimatorTitle.tsx | 2 +- .../lipsync/LipsyncEditor/LipsyncEditor.scss | 117 ++++++++++++++---- .../lipsync/LipsyncEditor/LipsyncEditor.tsx | 4 +- 14 files changed, 291 insertions(+), 105 deletions(-) create mode 100644 packages/fakeyou.com/src/components/providers/InferenceJobs/InferenceJobs.tsx create mode 100644 packages/fakeyou.com/src/components/providers/InferenceJobs/index.ts create mode 100644 packages/fakeyou.com/src/components/providers/index.ts create mode 100644 packages/fakeyou.com/src/context/InferenceJobsContext.tsx create mode 100644 packages/fakeyou.com/src/context/index.ts create mode 100644 packages/fakeyou.com/src/hooks/useInferenceJobs/index.ts create mode 100644 packages/fakeyou.com/src/hooks/useInferenceJobs/useInferenceJobs.tsx create mode 100644 packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx diff --git a/packages/fakeyou.com/src/App.tsx b/packages/fakeyou.com/src/App.tsx index 2da2b00a82..4380c46c10 100644 --- a/packages/fakeyou.com/src/App.tsx +++ b/packages/fakeyou.com/src/App.tsx @@ -57,6 +57,8 @@ import { VoiceConversionModelUploadJob } from "@storyteller/components/src/jobs/ import { VoiceConversionModelListItem } from "@storyteller/components/src/api/voice_conversion/ListVoiceConversionModels"; import HttpBackend from "i18next-http-backend"; +import { InferenceJobs } from "components/providers"; + // NB: We're transitioning over to this instance of i18n-next that loads translations over HTTP from Json Files. // The old i18n-next instance (see below) bakes in translations into the compiled javascript blob. // This new instance uses the Locize paid service to manage translation strings on their website. It's automated, @@ -779,6 +781,7 @@ class App extends React.Component<Props, State> { */} <div className="migrationComponentWrapper"> + <InferenceJobs {...{ byCategory: this.state.inferenceJobsByCategory }}> <Switch> <Route path="/"> <PageContainer @@ -876,6 +879,7 @@ class App extends React.Component<Props, State> { /> </Route> </Switch> + </InferenceJobs> </div> </div> </div> diff --git a/packages/fakeyou.com/src/components/providers/InferenceJobs/InferenceJobs.tsx b/packages/fakeyou.com/src/components/providers/InferenceJobs/InferenceJobs.tsx new file mode 100644 index 0000000000..b99bfc9ca7 --- /dev/null +++ b/packages/fakeyou.com/src/components/providers/InferenceJobs/InferenceJobs.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { JobState } from "@storyteller/components/src/jobs/JobStates"; +import { InferenceJob } from "@storyteller/components/src/jobs/InferenceJob"; +import { InferenceJobsContext } from 'context'; + +interface Props { + children?: any; + byCategory?: any; +} + +export default function InferenceJobs({ children, byCategory }: Props) { + const processStatus = (job: InferenceJob) => { + switch (job.jobState) { + case JobState.PENDING: + case JobState.UNKNOWN: return 0; + case JobState.STARTED: return 1 + case JobState.ATTEMPT_FAILED: return 2; + case JobState.COMPLETE_FAILURE: + case JobState.DEAD: return 3; + case JobState.COMPLETE_SUCCESS: return 4; + default: return -1; + } + }; + return <InferenceJobsContext.Provider {...{ value: { byCategory, processStatus } }}> + { children } + </InferenceJobsContext.Provider> +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/providers/InferenceJobs/index.ts b/packages/fakeyou.com/src/components/providers/InferenceJobs/index.ts new file mode 100644 index 0000000000..1989dab18d --- /dev/null +++ b/packages/fakeyou.com/src/components/providers/InferenceJobs/index.ts @@ -0,0 +1 @@ +export { default } from './InferenceJobs'; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/providers/index.ts b/packages/fakeyou.com/src/components/providers/index.ts new file mode 100644 index 0000000000..c38ad0d803 --- /dev/null +++ b/packages/fakeyou.com/src/components/providers/index.ts @@ -0,0 +1,3 @@ +import InferenceJobs from "./InferenceJobs"; + +export { InferenceJobs }; \ No newline at end of file diff --git a/packages/fakeyou.com/src/context/InferenceJobsContext.tsx b/packages/fakeyou.com/src/context/InferenceJobsContext.tsx new file mode 100644 index 0000000000..23ba0d6f9d --- /dev/null +++ b/packages/fakeyou.com/src/context/InferenceJobsContext.tsx @@ -0,0 +1,31 @@ +import { createContext } from 'react'; +import { JobState } from "@storyteller/components/src/jobs/JobStates"; +import { FrontendInferenceJobType, InferenceJob } from "@storyteller/components/src/jobs/InferenceJob"; + +function initInferenceJobsByCategoryMap() : Map<FrontendInferenceJobType, InferenceJob[]> { + let inferenceJobsByCategory = new Map(); + inferenceJobsByCategory.set(FrontendInferenceJobType.FaceAnimation, []); + inferenceJobsByCategory.set(FrontendInferenceJobType.TextToSpeech, []); + inferenceJobsByCategory.set(FrontendInferenceJobType.VoiceConversion, []); + return inferenceJobsByCategory; +}; + +const processStatus = (job: InferenceJob) => { + switch (job.jobState) { + case JobState.PENDING: + case JobState.UNKNOWN: return 0; + case JobState.STARTED: return 1 + case JobState.ATTEMPT_FAILED: return 2; + case JobState.COMPLETE_FAILURE: + case JobState.DEAD: return 3; + case JobState.COMPLETE_SUCCESS: return 4; + default: return -1; + } + }; + +// export default createContext({ +// byCategory: initInferenceJobsByCategoryMap(), +// nahmean: false +// }); + +export default createContext({ byCategory: initInferenceJobsByCategoryMap(), processStatus }); \ No newline at end of file diff --git a/packages/fakeyou.com/src/context/index.ts b/packages/fakeyou.com/src/context/index.ts new file mode 100644 index 0000000000..679d217f2e --- /dev/null +++ b/packages/fakeyou.com/src/context/index.ts @@ -0,0 +1,3 @@ +import InferenceJobsContext from "./InferenceJobsContext"; + +export { InferenceJobsContext }; \ No newline at end of file diff --git a/packages/fakeyou.com/src/hooks/index.tsx b/packages/fakeyou.com/src/hooks/index.tsx index 180f81aab4..c9e01ef0f9 100644 --- a/packages/fakeyou.com/src/hooks/index.tsx +++ b/packages/fakeyou.com/src/hooks/index.tsx @@ -2,7 +2,8 @@ import useFile from './useFile'; import useHover from './useHover'; import useId from './useId'; import useIdempotency from './useIdempotency'; +import useInferenceJobs from './useInferenceJobs'; import useLocalize from './useLocalize'; import useVideo from './useVideo'; -export { useFile, useHover, useId, useIdempotency, useLocalize, useVideo }; +export { useFile, useHover, useId, useIdempotency, useInferenceJobs, useLocalize, useVideo }; diff --git a/packages/fakeyou.com/src/hooks/useInferenceJobs/index.ts b/packages/fakeyou.com/src/hooks/useInferenceJobs/index.ts new file mode 100644 index 0000000000..99b97a8c16 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useInferenceJobs/index.ts @@ -0,0 +1 @@ +export { default } from './useInferenceJobs'; \ No newline at end of file diff --git a/packages/fakeyou.com/src/hooks/useInferenceJobs/useInferenceJobs.tsx b/packages/fakeyou.com/src/hooks/useInferenceJobs/useInferenceJobs.tsx new file mode 100644 index 0000000000..43a65160e5 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useInferenceJobs/useInferenceJobs.tsx @@ -0,0 +1,22 @@ +import { useContext } from 'react'; +import { FrontendInferenceJobType } from "@storyteller/components/src/jobs/InferenceJob"; +import { InferenceJobsContext } from 'context'; + + +interface Props { + inferenceJobsByCategory?: any; + type: number; +} + +export default function useInferenceJobs({ inferenceJobsByCategory, type }: Props) { + const { byCategory, processStatus } = useContext(InferenceJobsContext); + const jbs = byCategory.get(FrontendInferenceJobType.FaceAnimation) || []; + + return { + inferenceJobs: jbs.map((job,i) => ({ + ...job!, + statusIndex: processStatus(job!) + })), + processStatus + }; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx new file mode 100644 index 0000000000..ebd68e9a55 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx @@ -0,0 +1,91 @@ +import React, { useEffect, useState } from 'react'; +// import { a } from '@react-spring/web'; +import { + GetPendingTtsJobCount, + GetPendingTtsJobCountIsOk, + GetPendingTtsJobCountSuccessResponse, +} from "@storyteller/components/src/api/tts/GetPendingTtsJobCount"; +// import { springs } from "resources"; +import { useInferenceJobs } from "hooks"; +import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; +import { Analytics } from "common/Analytics"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faDownload, faHourglass1, faRemove, faTrophy, faWarning } from "@fortawesome/free-solid-svg-icons"; + +const DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS = 15000; + +export default function FaceAnimatorJobs({ t }: { t: any }) { + const { inferenceJobs = [] } = useInferenceJobs({ type: 0 }); + const [pending, pendingSet] = useState<GetPendingTtsJobCountSuccessResponse>({ + 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, + }); + const mediaLink = (path: string) => new BucketConfig().getGcsUrl(path); + const statusIcons = [faHourglass1,faHourglass1,faWarning,faRemove,faTrophy]; + const statusTxt = (which: number, config = {}) => ["animationPending","animationInProgress","animationFailed","animationDead","animationSuccess"].map((str,i) => t(`status.${str}`,config))[which]; + + // const processFail = (fail = "") => { + // switch (fail) { + // case "face_not_detected": return "Face not detected, try another picture"; + // default: return "Uknown failure"; + // } + // }; + + // const transitions = useTransition(inferenceJobs, { // not today + // ...springs.soft, + // from: { opacity: 0, position: "absolute" }, + // enter: { opacity: 1, position: "relative" }, + // leave: { opacity: 0, position: "absolute" }, + // }); + + useEffect(() => { + const fetch = async () => { + const response = await GetPendingTtsJobCount(); + if (GetPendingTtsJobCountIsOk(response)) { + if ( + response.cache_time.getTime() > pending.cache_time.getTime() + ) { + pendingSet(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, + pending.refresh_interval_millis + ); + const interval = setInterval(async () => fetch(), refreshInterval); + fetch(); + return () => clearInterval(interval); + }, [pending]); + + return inferenceJobs.length ? <div {...{ className: "face-animator-jobs panel" }}> + <h5>Your jobs</h5> + { inferenceJobs.map((job, key) => { + return <div {...{ className: "panel face-animator-job", key }}> + <FontAwesomeIcon {...{ className: `job-status-icon job-status-${job.statusIndex}`, icon: statusIcons[job.statusIndex] }}/> + <div {...{ className: "job-details" }}> + <h6> + { statusTxt(job.statusIndex,{ attemptCount: job.attemptCount || "" }) } + {/*{ job.maybeFailureCategory ? `: ${ processFail(job.maybeFailureCategory) }` : "" }*/} + </h6> + <span {...{ className: "job-id" }}>id: { job.jobToken }</span> + </div> + { + job.maybeResultToken ? <a {...{ + className: "btn btn-primary", + download: `fakeyou-${job.jobToken}.mp4`, + href: mediaLink(job.maybeResultPublicBucketMediaPath || ""), + onClick:() => Analytics.voiceConversionClickDownload() + }}> + <FontAwesomeIcon icon={faDownload} className="me-2" /> + { t("inputs.downloadFile") } + </a> : null + } + </div> + }).reverse()} + </div> : null; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorSuccess.tsx b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorSuccess.tsx index 5d57ca41f5..39f549802c 100644 --- a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorSuccess.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorSuccess.tsx @@ -1,82 +1,11 @@ -import React, { useEffect, useState } from 'react'; -import { animated } from '@react-spring/web'; -import { - GetPendingTtsJobCount, - GetPendingTtsJobCountIsOk, - GetPendingTtsJobCountSuccessResponse, -} from "@storyteller/components/src/api/tts/GetPendingTtsJobCount"; -import { FrontendInferenceJobType, InferenceJob } from "@storyteller/components/src/jobs/InferenceJob"; -import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; -import { JobState } from "@storyteller/components/src/jobs/JobStates"; -import { Analytics } from "common/Analytics"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faDownload } from "@fortawesome/free-solid-svg-icons"; +import React from 'react'; +import { a } from '@react-spring/web'; import { FaceAnimatorSlide } from "./FaceAnimatorTypes"; -const DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS = 15000; - -export default function FaceAnimatorSuccess({ audioProps, imageProps, style, enqueueInferenceJob, sessionSubscriptionsWrapper, inferenceJobsByCategory, t }: FaceAnimatorSlide) { - const [pending, pendingSet] = useState<GetPendingTtsJobCountSuccessResponse>({ - 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, - }); - const inferenceJobs = inferenceJobsByCategory.get(FrontendInferenceJobType.FaceAnimation)!; - const mediaLink = (path: string) => new BucketConfig().getGcsUrl(path); - const processStatus = (job: InferenceJob) => { - switch (job.jobState) { - case JobState.PENDING: - case JobState.UNKNOWN: return t("status.animationPending"); - case JobState.STARTED: return t("status.animationInProgress"); - case JobState.ATTEMPT_FAILED: return t("status.animationPending",{ attemptCount: job.attemptCount }); - case JobState.COMPLETE_FAILURE: - case JobState.DEAD: return t("status.animationDead"); - case JobState.COMPLETE_SUCCESS: return t("status.animationSuccess"); - } - }; - - useEffect(() => { - const fetch = async () => { - const response = await GetPendingTtsJobCount(); - if (GetPendingTtsJobCountIsOk(response)) { - if ( - response.cache_time.getTime() > pending.cache_time.getTime() - ) { - pendingSet(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, - pending.refresh_interval_millis - ); - const interval = setInterval(async () => fetch(), refreshInterval); - fetch(); - return () => clearInterval(interval); - }, [pending]); - - return <animated.div {...{ className: "lipsync-success", style }}> - <div {...{ className: "face-animator-results" }}>{ - inferenceJobs.map((job: any) => !job.maybeResultToken ? - <div> - <h3>{ processStatus(job) }</h3> - <span {...{ className: "job-id" }}>id: { job.jobToken }</span> - </div> : <div> - <h3>{ t("status.animationComplete") }</h3> - <span {...{ className: "job-id" }}>id: { job.jobToken }</span> - <a {...{ - className: "btn btn-primary w-100 mt-4", - download: `fakeyou-${job.jobToken}.mp4`, - href: mediaLink(job.maybeResultPublicBucketMediaPath), - onClick:() => Analytics.voiceConversionClickDownload() - }}> - <FontAwesomeIcon icon={faDownload} className="me-2" /> - { t("inputs.downloadFile") } - </a> - </div>).reverse() - }</div> - </animated.div>; +export default function FaceAnimatorSuccess({ style, t }: FaceAnimatorSlide) { + return <a.div {...{ className: "lipsync-success", style }}> + <div {...{ className: "face-animator-results" }}> + <h4>Animation added to queue!</h4> + </div> + </a.div>; }; \ No newline at end of file diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorTitle.tsx b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorTitle.tsx index cfe099fc67..e2d42d30e3 100644 --- a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorTitle.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorTitle.tsx @@ -86,7 +86,7 @@ export default function FaceAnimatorTitle({ ...rest }) { index: page, }} /> - <p {...{ className: "progress-description" }}>{t("headings.subtitle")}</p> + <p {...{ className: "progress-description fa-light-txt" }}>{t("headings.subtitle")}</p> </div> ); } diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.scss b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.scss index f4b01ae774..5de506eb8a 100644 --- a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.scss +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.scss @@ -4,6 +4,22 @@ $under992: max-width 992px; $over992: min-width 992px; +@mixin FAltTxt { color: #b6b6bb; } +@mixin FApanel { + padding: 1.5rem; + @include breakpoint($under992) { + padding: 1rem; + } +} + +.face-animator-main { + @include FApanel; + position: relative; + overflow: hidden; + + h1 { line-height: 1em;} +}; + .lipsync-editor { padding-top: 2rem; @@ -35,6 +51,7 @@ $over992: min-width 992px; .input-block { legend { + @include FAltTxt; font-size: .875rem; }; flex-grow: 1; @@ -77,6 +94,7 @@ $over992: min-width 992px; } .progress-description { + @include FAltTxt; margin-top: 1rem; width: 100%; } @@ -97,11 +115,6 @@ $over992: min-width 992px; } } -.lipsync-panel { - position: relative; - overflow: hidden; -} - .lipsync-working, .lipsync-working-notice { display: flex; @@ -122,31 +135,89 @@ $over992: min-width 992px; .lipsync-success { padding: 0.5rem 1rem 1rem; - h3 { + h4 { + @include FAltTxt; + text-align: center; margin: 1rem auto 0 0; } - - .job-id { - color: rgba(#fff, 0.66); - font-size: 0.75rem; - } } - .face-animator-mobile-sample { +.face-animator-mobile-sample { + padding: 1rem; + + @include breakpoint($over992) { + display: none; + } +} + +.face-animator-wide-sample { + flex: 1; + height: auto; + + @include breakpoint($under992) { + display: none; + } + + video { position: absolute ;} +} + +.face-animator-jobs { + @include FApanel; + h5 { + @include FAltTxt; + line-height: 1em; + } + margin-top: 1rem; + .face-animator-job { + display: flex; + flex-wrap: wrap; + margin-top: 1rem; padding: 1rem; - @include breakpoint($over992) { - display: none; - } - } - - .face-animator-wide-sample { - flex: 1; - height: auto; - @include breakpoint($under992) { - display: none; + margin-top: .5rem; + padding: .5rem; } - video { position: absolute ;} + .job-status-icon { + // background-color: red; + padding: .5rem; + height: 2rem; + width: 2rem; + border-radius: .5rem; + margin-right: 1rem; + } + + .job-status-1 { background-color: rgba(#89f, .6); } // started = blue + .job-status-2 { background-color: rgba(#efb700, .9); } // failed = yellow + .job-status-3 { background-color: rgba($primary, .6); } // dead = red + .job-status-4 { background-color: $success } // success = green + + .job-details { + // display: flex; + align-items: center; + height: 100%; + // width: 100%; + + h6 { line-height: 1em } + + } + + a { + white-space: nowrap; + margin: 0 0 0 auto; + + @include breakpoint($under992) { + margin: .5rem 0 0; + width: 100%; + } + } } + + .job-id { + @include FAltTxt; + line-height: 1em; + display: block; + font-size: 0.75rem; + } +} diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.tsx b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.tsx index daf0ea63d9..66e4587323 100644 --- a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.tsx @@ -22,6 +22,7 @@ import FaceAnimatorTitle from "./FaceAnimatorTitle"; import FaceAnimatorInput from './FaceAnimatorInput'; import FaceAnimatorWorking from './FaceAnimatorWorking'; import FaceAnimatorSuccess from "./FaceAnimatorSuccess"; +import FaceAnimatorJobs from "./FaceAnimatorJobs"; import { FaceAnimatorCore } from "./FaceAnimatorTypes"; import { BasicVideo } from "components/common"; import "./LipsyncEditor.scss"; @@ -141,7 +142,7 @@ export default function LipsyncEditor({ return ( <div {...{ className: "container-panel pt-4" }}> - <div {...{ className: "panel lipsync-panel p-3 py-4 p-md-4" }}> + <div {...{ className: "panel face-animator-main" }}> <FaceAnimatorTitle {...headerProps} /> {transitions((style, i) => { const Page = [FaceAnimatorInput, FaceAnimatorWorking, FaceAnimatorSuccess][page]; @@ -172,6 +173,7 @@ export default function LipsyncEditor({ ); })} </div> + <FaceAnimatorJobs {...{ inferenceJobsByCategory, t }}/> <div {...{ className: "face-animator-mobile-sample" }}> <BasicVideo {...{ src: "/videos/face-animator-instruction-en.mp4" }}/> </div> From 0ae073b4a358fd50a9dda0c12ec56c1f6f2f7d65 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Sat, 14 Oct 2023 15:27:43 +0700 Subject: [PATCH 12/51] sidebar overflow fix --- packages/fakeyou.com/src/scss/nav.scss | 19 ++++++++++++++++++- .../fakeyou.com/src/scss/site-refresh.scss | 13 +++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/fakeyou.com/src/scss/nav.scss b/packages/fakeyou.com/src/scss/nav.scss index 191435f266..988c6a3228 100644 --- a/packages/fakeyou.com/src/scss/nav.scss +++ b/packages/fakeyou.com/src/scss/nav.scss @@ -21,11 +21,28 @@ width: 0; height: 100%; margin-left: -260px; - overflow: auto; + overflow-x: hidden; -webkit-transition: all 0.2s ease; -moz-transition: all 0.2s ease; -o-transition: all 0.2s ease; transition: all 0.2s ease; + + &::-webkit-scrollbar { + width: 0; + } + + &::-webkit-scrollbar-thumb { + background-color: rgba($secondary, 1); + border-radius: 0.5rem; + } + + &::-webkit-scrollbar-track { + background-color: rgba($panel, 1) !important; + } + + &:hover::-webkit-scrollbar { + width: 10px; + } } #wrapper.toggled #sidebar-wrapper { diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index 3aa2e4c4c8..f72841e452 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -12,6 +12,19 @@ styles with important tags: // Once the rollout is complete, this outer wrapper class can be removed. .fakeyou-refresh { + ::-webkit-scrollbar-thumb { + background-color: rgba($secondary, 1); + border-radius: 0.5rem; + } + + ::-webkit-scrollbar-track { + background-color: rgba($bg, 1) !important; + } + + ::-webkit-scrollbar { + width: 10px; + } + p { font-weight: 400; margin-bottom: 0; From 3cef2b140e32f38d7d639aaccae6e8dcfffc2b87 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 13 Oct 2023 20:10:57 +0700 Subject: [PATCH 13/51] media page test --- .../fakeyou.com/src/v2/view/PageContainer.tsx | 5 ++ .../view/pages/media_page/AudioComponent.tsx | 20 ++++++ .../view/pages/media_page/ImageComponent.tsx | 21 ++++++ .../view/pages/media_page/MediaDataTypes.ts | 18 +++++ .../v2/view/pages/media_page/MediaPage.tsx | 66 +++++++++++++++++++ .../view/pages/media_page/VideoComponent.tsx | 18 +++++ .../tts/tts_result_view/TtsResultViewPage.tsx | 54 --------------- 7 files changed, 148 insertions(+), 54 deletions(-) create mode 100644 packages/fakeyou.com/src/v2/view/pages/media_page/AudioComponent.tsx create mode 100644 packages/fakeyou.com/src/v2/view/pages/media_page/ImageComponent.tsx create mode 100644 packages/fakeyou.com/src/v2/view/pages/media_page/MediaDataTypes.ts create mode 100644 packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx create mode 100644 packages/fakeyou.com/src/v2/view/pages/media_page/VideoComponent.tsx diff --git a/packages/fakeyou.com/src/v2/view/PageContainer.tsx b/packages/fakeyou.com/src/v2/view/PageContainer.tsx index 6c1298ee8e..b3f53f95c6 100644 --- a/packages/fakeyou.com/src/v2/view/PageContainer.tsx +++ b/packages/fakeyou.com/src/v2/view/PageContainer.tsx @@ -90,6 +90,7 @@ import MobileMenu from "components/layout/MobileMenu/MobileMenu"; import { TopNav } from "./nav/TopNav"; import { TestingPage } from "./pages/testing/TestingPage"; import TtsModelSearchPage from "./pages/tts/tts_model_search/TtsModelSearchPage"; +import MediaPage from "./pages/media_page/MediaPage"; interface Props { sessionWrapper: SessionWrapper; @@ -318,6 +319,10 @@ class PageContainer extends React.Component< /> </Route> + <Route path="/media/:token"> + <MediaPage /> + </Route> + <Route path="/dev-tts"> <TtsModelSearchPage sessionWrapper={this.props.sessionWrapper} /> </Route> diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/AudioComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media_page/AudioComponent.tsx new file mode 100644 index 0000000000..1a94a0e249 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/media_page/AudioComponent.tsx @@ -0,0 +1,20 @@ +import MediaData from "./MediaDataTypes"; + +import React from "react"; + +interface AudioComponentProps { + mediaData: MediaData; +} + +const AudioComponent: React.FC<AudioComponentProps> = ({ mediaData }) => { + return ( + <div> + <audio controls> + <source src={mediaData.public_bucket_path} /> + Your browser does not support the audio element. + </audio> + </div> + ); +}; + +export default AudioComponent; diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/ImageComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media_page/ImageComponent.tsx new file mode 100644 index 0000000000..e14dc65d51 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/media_page/ImageComponent.tsx @@ -0,0 +1,21 @@ +import React from "react"; +import MediaData from "./MediaDataTypes"; + +interface ImageComponentProps { + mediaData: MediaData; +} + +const ImageComponent: React.FC<ImageComponentProps> = ({ mediaData }) => { + return ( + <div> + <img + src={mediaData.public_bucket_path} + alt="test" // Make sure to provide alt text + width="400" + height="300" + /> + </div> + ); +}; + +export default ImageComponent; diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/MediaDataTypes.ts b/packages/fakeyou.com/src/v2/view/pages/media_page/MediaDataTypes.ts new file mode 100644 index 0000000000..cd22b4597f --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/media_page/MediaDataTypes.ts @@ -0,0 +1,18 @@ +export default interface MediaData { + token: string; + media_type: string; + public_bucket_path: string; + maybe_creator_user: { + user_token: string; + username: string; + display_name: string; + gravatar_hash: string; + default_avatar: { + image_index: number; + color_index: number; + }; + }; + creator_set_visibility: string; + created_at: string; + updated_at: string; +} diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx new file mode 100644 index 0000000000..ec4dfd07c8 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx @@ -0,0 +1,66 @@ +import React, { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; +import AudioComponent from "./AudioComponent"; +import VideoComponent from "./VideoComponent"; +import ImageComponent from "./ImageComponent"; + +const MediaFilePage = () => { + const { token } = useParams(); + const [mediaData, setMediaData] = useState<{ + /* media data properties */ + } | null>(null); + + // Dummy media data (replace with actual API data) + const dummyMediaData = { + token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", // Initialize with an empty string or your default token value + media_type: "video", // Change to "video" or "image" to test different types + public_bucket_path: + "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.wav", // Replace with actual URLs + maybe_creator_user: { + user_token: "u_00XGM6M2TE4J9", + username: "hanashi", + display_name: "hanashi", + gravatar_hash: "c45b453fcb1d27b348504ae7f5d6a6c", + default_avatar: { + image_index: 1, + color_index: 3, + }, + }, + creator_set_visibility: "public", + created_at: "2023-10-12T07:49:53Z", + updated_at: "2023-10-12T07:49:53Z", + }; + + // Simulate API call + useEffect(() => { + setTimeout(() => { + setMediaData(dummyMediaData); // Replace with actual API data + }, 1000); // Simulated delay of 1 second + }, [token]); + + const renderMediaComponent = () => { + if (!mediaData) { + return <div>Loading...</div>; + } + + switch (dummyMediaData.media_type) { + case "audio": + return <AudioComponent mediaData={dummyMediaData} />; + case "video": + return <VideoComponent mediaData={dummyMediaData} />; + case "image": + return <ImageComponent mediaData={dummyMediaData} />; + default: + return <div>Unsupported media type</div>; + } + }; + + return ( + <div> + <h1>{dummyMediaData.token}</h1> + {renderMediaComponent()} + </div> + ); +}; + +export default MediaFilePage; diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/VideoComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media_page/VideoComponent.tsx new file mode 100644 index 0000000000..8cb2a83941 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/media_page/VideoComponent.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import MediaData from "./MediaDataTypes"; +interface VideoComponentProps { + mediaData: MediaData; +} + +const VideoComponent: React.FC<VideoComponentProps> = ({ mediaData }) => { + return ( + <div> + <video controls width="640" height="360"> + <source src={mediaData.public_bucket_path} /> + Your browser does not support the video element. + </video> + </div> + ); +}; + +export default VideoComponent; diff --git a/packages/fakeyou.com/src/v2/view/pages/tts/tts_result_view/TtsResultViewPage.tsx b/packages/fakeyou.com/src/v2/view/pages/tts/tts_result_view/TtsResultViewPage.tsx index 8acbb7384a..39e36ceaba 100644 --- a/packages/fakeyou.com/src/v2/view/pages/tts/tts_result_view/TtsResultViewPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/tts/tts_result_view/TtsResultViewPage.tsx @@ -434,46 +434,6 @@ function TtsResultViewPage(props: Props) { <div className="container py-5"> <div className="d-flex flex-column"> <h1 className=" fw-bold mb-2">{headingTitle}</h1> - {/* Rate Result Buttons */} - {/* Commented out because not ready yet. */} - {/*<div className="d-flex gap-3"> - <div className="d-flex"> - <Tippy - content="I like this audio" - hideOnClick - placement="bottom" - theme="fakeyou" - arrow={false} - > - <button className="btn-rate left rated"> - <FontAwesomeIcon icon={faThumbsUp} /> - </button> - </Tippy> - - <div className="vr"></div> - - <Tippy - content="I dislike this audio" - hideOnClick - placement="bottom" - theme="fakeyou" - arrow={false} - > - <button className="btn-rate right"> - <FontAwesomeIcon icon={faThumbsDown} /> - </button> - </Tippy> - </div> - <div className="d-flex align-items-center"> - <FontAwesomeIcon - icon={faHeart} - className="me-2 rating-icon heart" - /> - <p> - <span className="fw-medium">1,518 likes</span> - </p> - </div> - </div>*/} <p className="mb-3 result-text pt-2"> <TextExpander @@ -494,14 +454,6 @@ function TtsResultViewPage(props: Props) { </div> </div> - {/* Without wavesurfer, - <audio - controls - src={audioLink}> - Your browser does not support the - <code>audio</code> element. - </audio>*/} - <div className="container-panel pt-3 pb-5">{socialSharing}</div> <div className="container-panel pt-3 pb-5"> @@ -517,12 +469,6 @@ function TtsResultViewPage(props: Props) { <div className="py-6"> <table className="table tts-result-table"> <tbody> - {/* <tr> - <th scope="row">Original text</th> - <td className="overflow-fix"> - {ttsInferenceResult.raw_inference_text} - </td> - </tr> */} <tr> <th scope="row">Audio creator</th> <td>{creatorDetails}</td> From 6495a10fcadfeb446ab2a0423e4ad350b6a555c6 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 13 Oct 2023 20:39:49 +0700 Subject: [PATCH 14/51] update --- .../src/v2/view/pages/media_page/MediaPage.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx index ec4dfd07c8..d61fe378da 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx @@ -6,16 +6,14 @@ import ImageComponent from "./ImageComponent"; const MediaFilePage = () => { const { token } = useParams(); - const [mediaData, setMediaData] = useState<{ - /* media data properties */ - } | null>(null); + const [mediaData, setMediaData] = useState<{} | null>(null); // Dummy media data (replace with actual API data) const dummyMediaData = { - token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", // Initialize with an empty string or your default token value - media_type: "video", // Change to "video" or "image" to test different types + token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", + media_type: "video", // Change to somthing like "video" or "image" to test different types public_bucket_path: - "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.wav", // Replace with actual URLs + "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.mp4", // Replace with actual URLs maybe_creator_user: { user_token: "u_00XGM6M2TE4J9", username: "hanashi", From 92133f2a4787e1cb769d1f3b70d37d4c17eafa76 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 13 Oct 2023 20:47:40 +0700 Subject: [PATCH 15/51] fixes --- packages/fakeyou.com/src/v2/view/PageContainer.tsx | 5 ++--- .../pages/{media_page => media}/AudioComponent.tsx | 0 .../pages/{media_page => media}/ImageComponent.tsx | 0 .../pages/{media_page => media}/MediaDataTypes.ts | 0 .../v2/view/pages/{media_page => media}/MediaPage.tsx | 4 ++-- .../pages/{media_page => media}/VideoComponent.tsx | 0 .../fakeyou.com/src/v2/view/pages/media/index.tsx | 3 --- .../fakeyou.com/src/v2/view/pages/media/media.tsx | 11 ----------- 8 files changed, 4 insertions(+), 19 deletions(-) rename packages/fakeyou.com/src/v2/view/pages/{media_page => media}/AudioComponent.tsx (100%) rename packages/fakeyou.com/src/v2/view/pages/{media_page => media}/ImageComponent.tsx (100%) rename packages/fakeyou.com/src/v2/view/pages/{media_page => media}/MediaDataTypes.ts (100%) rename packages/fakeyou.com/src/v2/view/pages/{media_page => media}/MediaPage.tsx (96%) rename packages/fakeyou.com/src/v2/view/pages/{media_page => media}/VideoComponent.tsx (100%) delete mode 100644 packages/fakeyou.com/src/v2/view/pages/media/index.tsx delete mode 100644 packages/fakeyou.com/src/v2/view/pages/media/media.tsx diff --git a/packages/fakeyou.com/src/v2/view/PageContainer.tsx b/packages/fakeyou.com/src/v2/view/PageContainer.tsx index b3f53f95c6..705249aba2 100644 --- a/packages/fakeyou.com/src/v2/view/PageContainer.tsx +++ b/packages/fakeyou.com/src/v2/view/PageContainer.tsx @@ -6,7 +6,6 @@ import { LoginPage } from "./pages/login/LoginPage"; import { ModerationFc } from "./pages/moderation/moderation_main/ModerationFc"; import { ModerationIpBanListFc } from "./pages/moderation/moderation_ip_ban_list/ModerationIpBanListFc"; import { ModerationViewIpBanFc } from "./pages/moderation/moderation_view_ip_ban/ModerationViewIpBanFc"; -import { Media } from "./pages/media"; import { LipsyncEditor } from "./pages/lipsync"; import { ProfileEditFc } from "./pages/profile/profile_edit/ProfileEditFc"; import { ProfilePage } from "./pages/profile/profile_view/ProfilePage"; @@ -90,7 +89,7 @@ import MobileMenu from "components/layout/MobileMenu/MobileMenu"; import { TopNav } from "./nav/TopNav"; import { TestingPage } from "./pages/testing/TestingPage"; import TtsModelSearchPage from "./pages/tts/tts_model_search/TtsModelSearchPage"; -import MediaPage from "./pages/media_page/MediaPage"; +import MediaPage from "./pages/media/MediaPage"; interface Props { sessionWrapper: SessionWrapper; @@ -469,7 +468,7 @@ class PageContainer extends React.Component< </Route> <Route path="/media/:token"> - <Media /> + <MediaPage /> </Route> <Route path="/moderation/user/list"> diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/AudioComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/AudioComponent.tsx similarity index 100% rename from packages/fakeyou.com/src/v2/view/pages/media_page/AudioComponent.tsx rename to packages/fakeyou.com/src/v2/view/pages/media/AudioComponent.tsx diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/ImageComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/ImageComponent.tsx similarity index 100% rename from packages/fakeyou.com/src/v2/view/pages/media_page/ImageComponent.tsx rename to packages/fakeyou.com/src/v2/view/pages/media/ImageComponent.tsx diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/MediaDataTypes.ts b/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts similarity index 100% rename from packages/fakeyou.com/src/v2/view/pages/media_page/MediaDataTypes.ts rename to packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx similarity index 96% rename from packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx rename to packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index d61fe378da..964f1afd3f 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media_page/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -4,7 +4,7 @@ import AudioComponent from "./AudioComponent"; import VideoComponent from "./VideoComponent"; import ImageComponent from "./ImageComponent"; -const MediaFilePage = () => { +const MediaPage = () => { const { token } = useParams(); const [mediaData, setMediaData] = useState<{} | null>(null); @@ -61,4 +61,4 @@ const MediaFilePage = () => { ); }; -export default MediaFilePage; +export default MediaPage; diff --git a/packages/fakeyou.com/src/v2/view/pages/media_page/VideoComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/VideoComponent.tsx similarity index 100% rename from packages/fakeyou.com/src/v2/view/pages/media_page/VideoComponent.tsx rename to packages/fakeyou.com/src/v2/view/pages/media/VideoComponent.tsx diff --git a/packages/fakeyou.com/src/v2/view/pages/media/index.tsx b/packages/fakeyou.com/src/v2/view/pages/media/index.tsx deleted file mode 100644 index f7c67981af..0000000000 --- a/packages/fakeyou.com/src/v2/view/pages/media/index.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import media from './media'; - -export { media as Media }; diff --git a/packages/fakeyou.com/src/v2/view/pages/media/media.tsx b/packages/fakeyou.com/src/v2/view/pages/media/media.tsx deleted file mode 100644 index ddc4db1725..0000000000 --- a/packages/fakeyou.com/src/v2/view/pages/media/media.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -interface Props { - value?: any; -} - -export default function media({ value }: Props) { - return <div> - <h1>Media</h1> - </div>; -}; \ No newline at end of file From 7d436267d578f81d3f877d5f48d210f9d74b5d8b Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Sat, 14 Oct 2023 06:48:28 +0700 Subject: [PATCH 16/51] changes --- .../src/v2/view/pages/media/MediaPage.tsx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 964f1afd3f..97037b4fd6 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -3,13 +3,14 @@ import { useParams } from "react-router-dom"; import AudioComponent from "./AudioComponent"; import VideoComponent from "./VideoComponent"; import ImageComponent from "./ImageComponent"; +import MediaData from "./MediaDataTypes"; const MediaPage = () => { - const { token } = useParams(); - const [mediaData, setMediaData] = useState<{} | null>(null); + const { token } = useParams<{ token: string }>(); + const [mediaData, setMediaData] = useState<MediaData | null>(null); // Dummy media data (replace with actual API data) - const dummyMediaData = { + let dummyMediaData = { token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", media_type: "video", // Change to somthing like "video" or "image" to test different types public_bucket_path: @@ -32,8 +33,8 @@ const MediaPage = () => { // Simulate API call useEffect(() => { setTimeout(() => { - setMediaData(dummyMediaData); // Replace with actual API data - }, 1000); // Simulated delay of 1 second + setMediaData(dummyMediaData); + }, 1000); }, [token]); const renderMediaComponent = () => { @@ -41,13 +42,13 @@ const MediaPage = () => { return <div>Loading...</div>; } - switch (dummyMediaData.media_type) { + switch (mediaData.media_type) { case "audio": - return <AudioComponent mediaData={dummyMediaData} />; + return <AudioComponent mediaData={mediaData} />; case "video": - return <VideoComponent mediaData={dummyMediaData} />; + return <VideoComponent mediaData={mediaData} />; case "image": - return <ImageComponent mediaData={dummyMediaData} />; + return <ImageComponent mediaData={mediaData} />; default: return <div>Unsupported media type</div>; } @@ -55,7 +56,7 @@ const MediaPage = () => { return ( <div> - <h1>{dummyMediaData.token}</h1> + <h1>{mediaData?.token}</h1> {renderMediaComponent()} </div> ); From e4e7fa94b343f49cbd6ca113be72894706a55971 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Sat, 14 Oct 2023 07:17:53 +0700 Subject: [PATCH 17/51] loading and error states --- .../fakeyou.com/src/v2/view/PageContainer.tsx | 6 +- .../src/v2/view/pages/media/MediaPage.tsx | 86 +++++++++++-------- 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/PageContainer.tsx b/packages/fakeyou.com/src/v2/view/PageContainer.tsx index 705249aba2..54d82b97d6 100644 --- a/packages/fakeyou.com/src/v2/view/PageContainer.tsx +++ b/packages/fakeyou.com/src/v2/view/PageContainer.tsx @@ -319,7 +319,7 @@ class PageContainer extends React.Component< </Route> <Route path="/media/:token"> - <MediaPage /> + <MediaPage sessionWrapper={this.props.sessionWrapper} /> </Route> <Route path="/dev-tts"> @@ -467,10 +467,6 @@ class PageContainer extends React.Component< <CreateCategoryPage sessionWrapper={this.props.sessionWrapper} /> </Route> - <Route path="/media/:token"> - <MediaPage /> - </Route> - <Route path="/moderation/user/list"> <ModerationUserListFc sessionWrapper={this.props.sessionWrapper} diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 97037b4fd6..52134575b4 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -4,62 +4,74 @@ import AudioComponent from "./AudioComponent"; import VideoComponent from "./VideoComponent"; import ImageComponent from "./ImageComponent"; import MediaData from "./MediaDataTypes"; +import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; -const MediaPage = () => { +interface MediaPageProps { + sessionWrapper: SessionWrapper; +} + +// Dummy media data (replace with actual API data) +let dummyMediaData = { + token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", + media_type: "video", // Change to somthing like "video" or "image" to test different types + public_bucket_path: + "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.mp4", // Replace with actual URLs + maybe_creator_user: { + user_token: "u_00XGM6M2TE4J9", + username: "hanashi", + display_name: "hanashi", + gravatar_hash: "c45b453fcb1d27b348504ae7f5d6a6c", + default_avatar: { + image_index: 1, + color_index: 3, + }, + }, + creator_set_visibility: "public", + created_at: "2023-10-12T07:49:53Z", + updated_at: "2023-10-12T07:49:53Z", +}; + +export default function MediaPage({ sessionWrapper }: MediaPageProps) { const { token } = useParams<{ token: string }>(); const [mediaData, setMediaData] = useState<MediaData | null>(null); - - // Dummy media data (replace with actual API data) - let dummyMediaData = { - token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", - media_type: "video", // Change to somthing like "video" or "image" to test different types - public_bucket_path: - "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.mp4", // Replace with actual URLs - maybe_creator_user: { - user_token: "u_00XGM6M2TE4J9", - username: "hanashi", - display_name: "hanashi", - gravatar_hash: "c45b453fcb1d27b348504ae7f5d6a6c", - default_avatar: { - image_index: 1, - color_index: 3, - }, - }, - creator_set_visibility: "public", - created_at: "2023-10-12T07:49:53Z", - updated_at: "2023-10-12T07:49:53Z", - }; + const [isLoading, setIsLoading] = useState<boolean>(true); + const [error, setError] = useState<boolean>(false); // Simulate API call useEffect(() => { setTimeout(() => { - setMediaData(dummyMediaData); + //Check if token is valid + if (token !== dummyMediaData.token) { + //if invalid token, set error to true + setError(true); + setIsLoading(false); + } else { + setMediaData(dummyMediaData); + setIsLoading(false); + } }, 1000); }, [token]); - const renderMediaComponent = () => { - if (!mediaData) { - return <div>Loading...</div>; - } - - switch (mediaData.media_type) { + function renderMediaComponent(data: MediaData) { + switch (data.media_type) { case "audio": - return <AudioComponent mediaData={mediaData} />; + return <AudioComponent mediaData={data} />; case "video": - return <VideoComponent mediaData={mediaData} />; + return <VideoComponent mediaData={data} />; case "image": - return <ImageComponent mediaData={mediaData} />; + return <ImageComponent mediaData={data} />; default: return <div>Unsupported media type</div>; } - }; + } + + if (isLoading) return <div>Loading...</div>; + if (error || !mediaData) return <div>Media not found</div>; return ( <div> <h1>{mediaData?.token}</h1> - {renderMediaComponent()} + {renderMediaComponent(mediaData)} </div> ); -}; - -export default MediaPage; +} From ba31bf47f9ae0fa2ec53eeba3d43c597fadb9da1 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Sat, 14 Oct 2023 13:06:58 +0700 Subject: [PATCH 18/51] many new components --- .../common/Accordion/Accordion.scss | 44 +++++++ .../components/common/Accordion/Accordion.tsx | 79 +++++++++++++ .../src/components/common/Accordion/index.ts | 1 + .../common/DataTable/DataTable.scss | 31 +++++ .../components/common/DataTable/DataTable.tsx | 26 ++++ .../src/components/common/DataTable/index.tsx | 1 + .../components/common/Skeleton/Skeleton.scss | 37 ++++++ .../components/common/Skeleton/Skeleton.tsx | 13 ++ .../src/components/common/Skeleton/index.ts | 1 + .../layout/PageHeader/PageHeader.tsx | 2 +- .../fakeyou.com/src/scss/site-refresh.scss | 2 +- .../v2/view/pages/media/AudioComponent.tsx | 4 +- .../src/v2/view/pages/media/MediaPage.tsx | 111 ++++++++++++++++-- .../v2/view/pages/media/VideoComponent.tsx | 16 +-- 14 files changed, 345 insertions(+), 23 deletions(-) create mode 100644 packages/fakeyou.com/src/components/common/Accordion/Accordion.scss create mode 100644 packages/fakeyou.com/src/components/common/Accordion/Accordion.tsx create mode 100644 packages/fakeyou.com/src/components/common/Accordion/index.ts create mode 100644 packages/fakeyou.com/src/components/common/DataTable/DataTable.scss create mode 100644 packages/fakeyou.com/src/components/common/DataTable/DataTable.tsx create mode 100644 packages/fakeyou.com/src/components/common/DataTable/index.tsx create mode 100644 packages/fakeyou.com/src/components/common/Skeleton/Skeleton.scss create mode 100644 packages/fakeyou.com/src/components/common/Skeleton/Skeleton.tsx create mode 100644 packages/fakeyou.com/src/components/common/Skeleton/index.ts diff --git a/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss b/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss new file mode 100644 index 0000000000..8fd9d8ee37 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss @@ -0,0 +1,44 @@ +@import "scss/colours.scss"; + +.fy-accordion-item { + border: 1px solid rgba($white, 0.12); + border-radius: 5px; + overflow: hidden; +} + +.fy-accordion-header { + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + background-color: $secondary; + transition: all 0.2s ease; + + &.open { + background-color: lighten($secondary, 5%); + } +} + +.fy-accordion-content { + overflow: hidden; + background-color: lighten($panel, 4%); + + &.open { + opacity: 1; + max-height: 100%; + visibility: visible; + } +} + +.fy-accordion-content table { + width: 100%; +} + +.caret-icon { + transition: transform 0.2s ease; + transform-origin: center; +} + +.caret-rotated { + transform: rotate(180deg); +} diff --git a/packages/fakeyou.com/src/components/common/Accordion/Accordion.tsx b/packages/fakeyou.com/src/components/common/Accordion/Accordion.tsx new file mode 100644 index 0000000000..7d6daab7c6 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Accordion/Accordion.tsx @@ -0,0 +1,79 @@ +import React, { useState, useRef, useEffect } from "react"; +import "./Accordion.scss"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faChevronDown } from "@fortawesome/pro-solid-svg-icons"; +import { animated, useSpring } from "@react-spring/web"; + +interface AccordionProps { + children: React.ReactNode; +} + +interface AccordionItemProps { + title: string; + defaultOpen?: boolean; + children: React.ReactNode; +} + +function AccordionItem({ + title, + defaultOpen = false, + children, +}: AccordionItemProps) { + const [isOpen, setIsOpen] = useState(defaultOpen); + const [contentHeight, setContentHeight] = useState<number | undefined>( + defaultOpen ? undefined : 0 + ); + const contentRef = useRef<HTMLDivElement>(null); + + useEffect(() => { + if (isOpen && contentRef.current) { + setContentHeight(contentRef.current.scrollHeight); + } else { + setContentHeight(0); + } + }, [isOpen]); + + const heightProps = useSpring({ + height: `${contentHeight}px`, + from: { + height: defaultOpen ? "auto" : "0px", + config: { tension: 300, friction: 25 }, + }, + }); + + const contentOpacityProps = useSpring({ + opacity: isOpen ? 1 : 0, + config: { tension: 300, friction: 25 }, + }); + + return ( + <div className="fy-accordion-item"> + <div + className={`fy-accordion-header p-3 ${isOpen ? "open" : ""}`} + onClick={() => setIsOpen(!isOpen)} + > + {title} + <span className={`caret-icon ${isOpen ? "caret-rotated" : ""}`}> + <FontAwesomeIcon icon={faChevronDown} /> + </span> + </div> + <animated.div style={heightProps}> + <animated.div + ref={contentRef} + style={contentOpacityProps} + className="fy-accordion-content" + > + {children} + </animated.div> + </animated.div> + </div> + ); +} + +function Accordion({ children }: AccordionProps) { + return <div className="d-flex flex-column gap-3">{children}</div>; +} + +Accordion.Item = AccordionItem; + +export default Accordion; diff --git a/packages/fakeyou.com/src/components/common/Accordion/index.ts b/packages/fakeyou.com/src/components/common/Accordion/index.ts new file mode 100644 index 0000000000..366853b1f2 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Accordion/index.ts @@ -0,0 +1 @@ +export { default } from "./Accordion"; diff --git a/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss b/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss new file mode 100644 index 0000000000..1d3483e027 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss @@ -0,0 +1,31 @@ +@import "scss/colours.scss"; + +table { + margin-bottom: 0 !important; +} + +td { + padding: 8px 16px !important; +} + +.no-outer-border { + border: none !important; +} + +.no-outer-border > thead > tr > th:first-child, +.no-outer-border > tbody > tr > td:first-child { + border-left: none !important; +} + +.no-outer-border > thead > tr > th:last-child, +.no-outer-border > tbody > tr > td:last-child { + border-right: none !important; +} + +.no-outer-border > tbody > tr:last-child > td { + border-bottom: none !important; +} + +.data-table-property { + background-color: lighten($panel, 7%) !important; +} diff --git a/packages/fakeyou.com/src/components/common/DataTable/DataTable.tsx b/packages/fakeyou.com/src/components/common/DataTable/DataTable.tsx new file mode 100644 index 0000000000..28ff89d7e4 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/DataTable/DataTable.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import "./DataTable.scss"; + +type Data = { + property: string; + value: string; +}; + +interface DataTableProps { + data: Data[]; +} + +export default function DataTable({ data }: DataTableProps) { + return ( + <table className="table no-outer-border"> + <tbody> + {data.map((row, index) => ( + <tr key={index}> + <td className="data-table-property">{row.property}</td> + <td>{row.value}</td> + </tr> + ))} + </tbody> + </table> + ); +} diff --git a/packages/fakeyou.com/src/components/common/DataTable/index.tsx b/packages/fakeyou.com/src/components/common/DataTable/index.tsx new file mode 100644 index 0000000000..e8a1b251a1 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/DataTable/index.tsx @@ -0,0 +1 @@ +export { default } from "./DataTable"; diff --git a/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.scss b/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.scss new file mode 100644 index 0000000000..a2f59e40b5 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.scss @@ -0,0 +1,37 @@ +@import "scss/colours.scss"; + +.skeleton { + background: linear-gradient( + -90deg, + rgba($white, 10%) 25%, + rgba(darken($white, 20%), 10%) 50%, + rgba($white, 10%) 75% + ); + background-size: 200% 100%; + animation: loading 1.5s infinite; + border-radius: 0.25rem; + width: 100%; + height: 1em; + display: inline-block; +} + +@keyframes loading { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} + +.skeleton.rounded { + border-radius: 50%; +} + +.skeleton.medium { + width: 40%; +} + +.skeleton.short { + width: 20%; +} diff --git a/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.tsx b/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.tsx new file mode 100644 index 0000000000..1ca5a22671 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Skeleton/Skeleton.tsx @@ -0,0 +1,13 @@ +import React from "react"; +import "./Skeleton.scss"; + +interface SkeletonProps { + type?: "full" | "medium" | "short"; + rounded?: boolean; +} + +export default function Skeleton({ type = "full", rounded }: SkeletonProps) { + const skeletonClass = `skeleton ${type} ${rounded && "rounded"}`; + + return <div className={skeletonClass}></div>; +} diff --git a/packages/fakeyou.com/src/components/common/Skeleton/index.ts b/packages/fakeyou.com/src/components/common/Skeleton/index.ts new file mode 100644 index 0000000000..2508b14587 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/Skeleton/index.ts @@ -0,0 +1 @@ +export { default } from "./Skeleton"; diff --git a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx index 62682ba82d..464328c665 100644 --- a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx +++ b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx @@ -6,7 +6,7 @@ import Button from "components/common/Button"; interface PageHeaderProps { titleIcon?: IconDefinition; - title: string; + title: string | React.ReactNode; subText: string | React.ReactNode; full?: boolean; showButton?: boolean; diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index f72841e452..9943d8b6f9 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -1517,7 +1517,7 @@ textarea { padding-left: var(--bs-gutter-x, 1rem); margin-right: auto; margin-left: auto; - max-width: 1080px; + max-width: 1200px; border-radius: 0.5rem; } diff --git a/packages/fakeyou.com/src/v2/view/pages/media/AudioComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/AudioComponent.tsx index 1a94a0e249..dc2763baad 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/AudioComponent.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/AudioComponent.tsx @@ -8,8 +8,8 @@ interface AudioComponentProps { const AudioComponent: React.FC<AudioComponentProps> = ({ mediaData }) => { return ( - <div> - <audio controls> + <div className="w-100"> + <audio className="w-100" controls> <source src={mediaData.public_bucket_path} /> Your browser does not support the audio element. </audio> diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 52134575b4..955a91d5be 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -1,10 +1,19 @@ import React, { useEffect, useState } from "react"; -import { useParams } from "react-router-dom"; +import { Link, useParams } from "react-router-dom"; import AudioComponent from "./AudioComponent"; import VideoComponent from "./VideoComponent"; import ImageComponent from "./ImageComponent"; import MediaData from "./MediaDataTypes"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; +import Container from "components/common/Container"; +import Panel from "components/common/Panel"; +import PageHeader from "components/layout/PageHeader"; +import Skeleton from "components/common/Skeleton"; +import Button from "components/common/Button"; +import { faCircleExclamation } from "@fortawesome/pro-solid-svg-icons"; +import Accordion from "components/common/Accordion"; +import DataTable from "components/common/DataTable"; +import { Gravatar } from "@storyteller/components/src/elements/Gravatar"; interface MediaPageProps { sessionWrapper: SessionWrapper; @@ -19,7 +28,7 @@ let dummyMediaData = { maybe_creator_user: { user_token: "u_00XGM6M2TE4J9", username: "hanashi", - display_name: "hanashi", + display_name: "Hanashi", gravatar_hash: "c45b453fcb1d27b348504ae7f5d6a6c", default_avatar: { image_index: 1, @@ -57,7 +66,12 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { case "audio": return <AudioComponent mediaData={data} />; case "video": - return <VideoComponent mediaData={data} />; + return ( + <div className="ratio ratio-16x9"> + <VideoComponent mediaData={data} /> + </div> + ); + case "image": return <ImageComponent mediaData={data} />; default: @@ -65,13 +79,92 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { } } - if (isLoading) return <div>Loading...</div>; - if (error || !mediaData) return <div>Media not found</div>; + if (isLoading) + return ( + <Container type="panel"> + <PageHeader + title={<Skeleton type="medium" />} + subText={<Skeleton type="short" />} + /> + <Panel padding={true}> + <div className="row"> + <div className="col-12 col-md-8"> + <h1 className="mb-0"> + <Skeleton /> + </h1> + </div> + <div className="col-12 col-md-4"> + <h1 className="mb-0"> + <Skeleton /> + </h1> + </div> + </div> + </Panel> + </Container> + ); + + if (error || !mediaData) + return ( + <Container type="panel"> + <PageHeader + titleIcon={faCircleExclamation} + title="Media not found" + subText="This media does not exist or is private." + extension={ + <div className="d-flex"> + <Button label="Back to homepage" to="/" className="d-flex" /> + </div> + } + /> + </Container> + ); + + const mediaDetails = [ + { property: "Type", value: mediaData.media_type }, + { property: "Created at", value: mediaData.created_at }, + { property: "Visibility", value: mediaData.creator_set_visibility }, + { property: "Model Used", value: "Model Name" }, + ]; return ( - <div> - <h1>{mediaData?.token}</h1> - {renderMediaComponent(mediaData)} - </div> + <Container type="panel"> + <PageHeader + title="Model name" + subText={mediaData.maybe_creator_user.display_name} + /> + <Panel padding={true}> + <div className="row g-4"> + <div className="col-12 col-lg-8"> + {renderMediaComponent(mediaData)} + </div> + <div className="col-12 col-lg-4"> + <div className="d-flex"> + <Gravatar + size={50} + username={mediaData.maybe_creator_user.display_name} + avatarIndex={ + mediaData.maybe_creator_user.default_avatar.image_index + } + backgroundIndex={ + mediaData.maybe_creator_user.default_avatar.color_index + } + /> + <div className="d-flex flex-column"> + <Link + to={`/profile/${mediaData.maybe_creator_user.display_name}`} + > + {mediaData.maybe_creator_user.display_name} + </Link> + </div> + </div> + <Accordion> + <Accordion.Item title="Details" defaultOpen={true}> + <DataTable data={mediaDetails} /> + </Accordion.Item> + </Accordion> + </div> + </div> + </Panel> + </Container> ); } diff --git a/packages/fakeyou.com/src/v2/view/pages/media/VideoComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/VideoComponent.tsx index 8cb2a83941..7cdd161ce4 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/VideoComponent.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/VideoComponent.tsx @@ -4,15 +4,11 @@ interface VideoComponentProps { mediaData: MediaData; } -const VideoComponent: React.FC<VideoComponentProps> = ({ mediaData }) => { +export default function VideoComponent({ mediaData }: VideoComponentProps) { return ( - <div> - <video controls width="640" height="360"> - <source src={mediaData.public_bucket_path} /> - Your browser does not support the video element. - </video> - </div> + <video className="rounded" controls width="100%" height="auto"> + <source src={mediaData.public_bucket_path} /> + Your browser does not support the video element. + </video> ); -}; - -export default VideoComponent; +} From a7bd1d97c2517fff3b5dfbb3656c4b705269702d Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Sat, 14 Oct 2023 14:11:01 +0700 Subject: [PATCH 19/51] profile image and time update --- packages/fakeyou.com/package.json | 2 +- .../common/Accordion/Accordion.scss | 2 +- .../components/common/Accordion/Accordion.tsx | 72 ++++++++++++++----- .../common/DataTable/DataTable.scss | 2 + .../fakeyou.com/src/hooks/useTimeAgo/index.ts | 1 + .../src/hooks/useTimeAgo/useTimeAgo.tsx | 44 ++++++++++++ .../fakeyou.com/src/scss/site-refresh.scss | 2 +- .../src/v2/view/pages/media/MediaDataTypes.ts | 2 + .../src/v2/view/pages/media/MediaPage.tsx | 28 +++++--- yarn.lock | 8 +++ 10 files changed, 135 insertions(+), 28 deletions(-) create mode 100644 packages/fakeyou.com/src/hooks/useTimeAgo/index.ts create mode 100644 packages/fakeyou.com/src/hooks/useTimeAgo/useTimeAgo.tsx diff --git a/packages/fakeyou.com/package.json b/packages/fakeyou.com/package.json index f89e903dca..a0849337e4 100644 --- a/packages/fakeyou.com/package.json +++ b/packages/fakeyou.com/package.json @@ -33,7 +33,7 @@ "axios": "^0.21.0", "bulma": "^0.9.0", "craco": "^0.0.3", - "date-fns": "^2.22.1", + "date-fns": "2.22.1", "framer-motion": "^6.5.1", "howler": "^2.2.0", "i18next": "^21.6.11", diff --git a/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss b/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss index 8fd9d8ee37..fcb40c3a17 100644 --- a/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss +++ b/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss @@ -2,7 +2,7 @@ .fy-accordion-item { border: 1px solid rgba($white, 0.12); - border-radius: 5px; + border-radius: 0.5rem; overflow: hidden; } diff --git a/packages/fakeyou.com/src/components/common/Accordion/Accordion.tsx b/packages/fakeyou.com/src/components/common/Accordion/Accordion.tsx index 7d6daab7c6..4eceaeee37 100644 --- a/packages/fakeyou.com/src/components/common/Accordion/Accordion.tsx +++ b/packages/fakeyou.com/src/components/common/Accordion/Accordion.tsx @@ -1,4 +1,10 @@ -import React, { useState, useRef, useEffect } from "react"; +import React, { + useState, + useRef, + useEffect, + createContext, + useContext, +} from "react"; import "./Accordion.scss"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faChevronDown } from "@fortawesome/pro-solid-svg-icons"; @@ -14,50 +20,62 @@ interface AccordionItemProps { children: React.ReactNode; } +interface AccordionContextType { + openItems: string[]; + toggleItem: (title: string) => void; +} + +const AccordionContext = createContext<AccordionContextType | undefined>( + undefined +); + function AccordionItem({ title, defaultOpen = false, children, }: AccordionItemProps) { - const [isOpen, setIsOpen] = useState(defaultOpen); + const { openItems, toggleItem } = useContext( + AccordionContext + ) as AccordionContextType; + const isOpen = openItems.includes(title); + const [contentHeight, setContentHeight] = useState<number | undefined>( - defaultOpen ? undefined : 0 + isOpen ? undefined : 0 ); const contentRef = useRef<HTMLDivElement>(null); useEffect(() => { - if (isOpen && contentRef.current) { - setContentHeight(contentRef.current.scrollHeight); - } else { - setContentHeight(0); + if (contentRef.current) { + setContentHeight(isOpen ? contentRef.current.scrollHeight : 0); } }, [isOpen]); const heightProps = useSpring({ - height: `${contentHeight}px`, - from: { - height: defaultOpen ? "auto" : "0px", - config: { tension: 300, friction: 25 }, - }, + height: isOpen ? `${contentHeight}px` : "0px", + config: { tension: 300, friction: 25, clamp: true }, }); const contentOpacityProps = useSpring({ opacity: isOpen ? 1 : 0, - config: { tension: 300, friction: 25 }, + config: { tension: 300, friction: 25, clamp: true }, }); + const handleClick = () => { + toggleItem(title); + }; + return ( <div className="fy-accordion-item"> <div className={`fy-accordion-header p-3 ${isOpen ? "open" : ""}`} - onClick={() => setIsOpen(!isOpen)} + onClick={handleClick} > {title} <span className={`caret-icon ${isOpen ? "caret-rotated" : ""}`}> <FontAwesomeIcon icon={faChevronDown} /> </span> </div> - <animated.div style={heightProps}> + <animated.div style={{ ...heightProps, overflow: "hidden" }}> <animated.div ref={contentRef} style={contentOpacityProps} @@ -71,7 +89,29 @@ function AccordionItem({ } function Accordion({ children }: AccordionProps) { - return <div className="d-flex flex-column gap-3">{children}</div>; + const [openItems, setOpenItems] = useState<string[]>([]); + + const toggleItem = (title: string) => { + if (openItems.includes(title)) { + setOpenItems(openItems.filter((item) => item !== title)); + } else { + setOpenItems([...openItems, title]); + } + }; + + // Initialize openItems based on defaultOpen props of AccordionItem children + useEffect(() => { + const defaultOpenItems = React.Children.toArray(children) + .filter((child: any) => child.props.defaultOpen) + .map((child: any) => child.props.title); + setOpenItems(defaultOpenItems); + }, [children]); + + return ( + <AccordionContext.Provider value={{ openItems, toggleItem }}> + <div className="d-flex flex-column gap-3">{children}</div> + </AccordionContext.Provider> + ); } Accordion.Item = AccordionItem; diff --git a/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss b/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss index 1d3483e027..dc19b4a6c7 100644 --- a/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss +++ b/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss @@ -1,11 +1,13 @@ @import "scss/colours.scss"; table { + font-size: 14px; margin-bottom: 0 !important; } td { padding: 8px 16px !important; + min-width: 124px !important; } .no-outer-border { diff --git a/packages/fakeyou.com/src/hooks/useTimeAgo/index.ts b/packages/fakeyou.com/src/hooks/useTimeAgo/index.ts new file mode 100644 index 0000000000..039f2a67f4 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useTimeAgo/index.ts @@ -0,0 +1 @@ +export { default } from "./useTimeAgo"; diff --git a/packages/fakeyou.com/src/hooks/useTimeAgo/useTimeAgo.tsx b/packages/fakeyou.com/src/hooks/useTimeAgo/useTimeAgo.tsx new file mode 100644 index 0000000000..4137c46b27 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useTimeAgo/useTimeAgo.tsx @@ -0,0 +1,44 @@ +import { useEffect, useState } from "react"; + +function useTimeAgo(timestamp: string) { + const [timeAgo, setTimeAgo] = useState<string>(""); + + useEffect(() => { + const calculateTimeAgo = () => { + const now = new Date(); + const then = new Date(timestamp); + + const seconds = Math.floor((now.getTime() - then.getTime()) / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + const months = Math.floor(days / 30); + const years = Math.floor(months / 12); + + if (years > 0) { + setTimeAgo(`${years} ${years === 1 ? "year" : "years"} ago`); + } else if (months > 0) { + setTimeAgo(`${months} ${months === 1 ? "month" : "months"} ago`); + } else if (days > 0) { + setTimeAgo(`${days} ${days === 1 ? "day" : "days"} ago`); + } else if (hours > 0) { + setTimeAgo(`${hours} ${hours === 1 ? "hour" : "hours"} ago`); + } else if (minutes > 0) { + setTimeAgo(`${minutes} ${minutes === 1 ? "minute" : "minutes"} ago`); + } else { + setTimeAgo(`${seconds} ${seconds === 1 ? "second" : "seconds"} ago`); + } + }; + + calculateTimeAgo(); + + // Update the time difference every minute + const intervalId = setInterval(calculateTimeAgo, 60000); + + return () => clearInterval(intervalId); + }, [timestamp]); + + return timeAgo; +} + +export default useTimeAgo; diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index 9943d8b6f9..49acbb1051 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -148,7 +148,7 @@ styles with important tags: } .container { - max-width: 1080px !important; + max-width: 1200px !important; } .container, diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts b/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts index cd22b4597f..97148a2014 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts @@ -12,6 +12,8 @@ export default interface MediaData { color_index: number; }; }; + model_used: string; + model_link: string; creator_set_visibility: string; created_at: string; updated_at: string; diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 955a91d5be..4a6e111a3b 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -14,6 +14,7 @@ import { faCircleExclamation } from "@fortawesome/pro-solid-svg-icons"; import Accordion from "components/common/Accordion"; import DataTable from "components/common/DataTable"; import { Gravatar } from "@storyteller/components/src/elements/Gravatar"; +import useTimeAgo from "hooks/useTimeAgo"; interface MediaPageProps { sessionWrapper: SessionWrapper; @@ -35,9 +36,11 @@ let dummyMediaData = { color_index: 3, }, }, + model_used: "Ash Ketchum", + model_link: "/tts/TM:6g1mfb9b6fb8", creator_set_visibility: "public", - created_at: "2023-10-12T07:49:53Z", - updated_at: "2023-10-12T07:49:53Z", + created_at: "2023-05-12T07:49:53Z", + updated_at: "2023-05-12T07:49:53Z", }; export default function MediaPage({ sessionWrapper }: MediaPageProps) { @@ -46,6 +49,8 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { const [isLoading, setIsLoading] = useState<boolean>(true); const [error, setError] = useState<boolean>(false); + const timeCreated = useTimeAgo(mediaData?.created_at || ""); + // Simulate API call useEffect(() => { setTimeout(() => { @@ -88,12 +93,12 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { /> <Panel padding={true}> <div className="row"> - <div className="col-12 col-md-8"> + <div className="col-12 col-xl-8"> <h1 className="mb-0"> <Skeleton /> </h1> </div> - <div className="col-12 col-md-4"> + <div className="col-12 col-xl-4"> <h1 className="mb-0"> <Skeleton /> </h1> @@ -123,7 +128,10 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { { property: "Type", value: mediaData.media_type }, { property: "Created at", value: mediaData.created_at }, { property: "Visibility", value: mediaData.creator_set_visibility }, - { property: "Model Used", value: "Model Name" }, + { + property: "Model", + value: mediaData.model_used, + }, ]; return ( @@ -134,13 +142,13 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { /> <Panel padding={true}> <div className="row g-4"> - <div className="col-12 col-lg-8"> + <div className="col-12 col-xl-8"> {renderMediaComponent(mediaData)} </div> - <div className="col-12 col-lg-4"> - <div className="d-flex"> + <div className="col-12 col-xl-4"> + <div className="d-flex mb-3 gap-2"> <Gravatar - size={50} + size={48} username={mediaData.maybe_creator_user.display_name} avatarIndex={ mediaData.maybe_creator_user.default_avatar.image_index @@ -151,10 +159,12 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { /> <div className="d-flex flex-column"> <Link + className="fw-medium" to={`/profile/${mediaData.maybe_creator_user.display_name}`} > {mediaData.maybe_creator_user.display_name} </Link> + {timeCreated} </div> </div> <Accordion> diff --git a/yarn.lock b/yarn.lock index b6f99c3d43..16f51c2909 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4570,6 +4570,7 @@ __metadata: dependencies: "@react-spring/types": ^9.7.3 craco: ^0.0.3 + date-fns: 2.22.1 lerna: ^4.0.0 yarn: ^1.22.19 languageName: unknown @@ -8966,6 +8967,13 @@ __metadata: languageName: node linkType: hard +"date-fns@npm:2.22.1": + version: 2.22.1 + resolution: "date-fns@npm:2.22.1" + checksum: 7ff97cd605af50c02f341687c2cafd218839a1aace67965374989855a13f76dc4fe52e0e38c343c1ad1f8399787cb6839a0b14a669c44b30550c287300b1bb50 + languageName: node + linkType: hard + "date-fns@npm:^2.22.1": version: 2.28.0 resolution: "date-fns@npm:2.28.0" From a7a946780e4d0697dba5b4b6477cfa2d4c5322bd Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Sat, 14 Oct 2023 14:12:29 +0700 Subject: [PATCH 20/51] font-weight change --- .../fakeyou.com/src/components/common/Accordion/Accordion.scss | 1 + .../fakeyou.com/src/components/common/DataTable/DataTable.scss | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss b/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss index fcb40c3a17..803aeb60d5 100644 --- a/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss +++ b/packages/fakeyou.com/src/components/common/Accordion/Accordion.scss @@ -13,6 +13,7 @@ cursor: pointer; background-color: $secondary; transition: all 0.2s ease; + font-weight: 500; &.open { background-color: lighten($secondary, 5%); diff --git a/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss b/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss index dc19b4a6c7..e5299b7c8e 100644 --- a/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss +++ b/packages/fakeyou.com/src/components/common/DataTable/DataTable.scss @@ -29,5 +29,6 @@ td { } .data-table-property { + font-weight: 500 !important; background-color: lighten($panel, 7%) !important; } From ff529ebf31ff2f828cf68369f2f055b26cc8a0a0 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Sat, 14 Oct 2023 17:06:12 +0700 Subject: [PATCH 21/51] updates and audio player --- .../components/common/DataTable/DataTable.tsx | 10 +- .../layout/PageHeader/PageHeader.tsx | 6 + .../v2/view/pages/media/AudioComponent.tsx | 20 --- .../view/pages/media/MediaAudioComponent.tsx | 17 ++ .../v2/view/pages/media/MediaAudioPlayer.tsx | 150 ++++++++++++++++++ ...eComponent.tsx => MediaImageComponent.tsx} | 12 +- .../src/v2/view/pages/media/MediaPage.tsx | 103 +++++++++--- ...oComponent.tsx => MediaVideoComponent.tsx} | 7 +- 8 files changed, 277 insertions(+), 48 deletions(-) delete mode 100644 packages/fakeyou.com/src/v2/view/pages/media/AudioComponent.tsx create mode 100644 packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx create mode 100644 packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx rename packages/fakeyou.com/src/v2/view/pages/media/{ImageComponent.tsx => MediaImageComponent.tsx} (55%) rename packages/fakeyou.com/src/v2/view/pages/media/{VideoComponent.tsx => MediaVideoComponent.tsx} (70%) diff --git a/packages/fakeyou.com/src/components/common/DataTable/DataTable.tsx b/packages/fakeyou.com/src/components/common/DataTable/DataTable.tsx index 28ff89d7e4..539e82317e 100644 --- a/packages/fakeyou.com/src/components/common/DataTable/DataTable.tsx +++ b/packages/fakeyou.com/src/components/common/DataTable/DataTable.tsx @@ -1,9 +1,11 @@ import React from "react"; import "./DataTable.scss"; +import { Link } from "react-router-dom"; type Data = { property: string; value: string; + link?: string; }; interface DataTableProps { @@ -17,7 +19,13 @@ export default function DataTable({ data }: DataTableProps) { {data.map((row, index) => ( <tr key={index}> <td className="data-table-property">{row.property}</td> - <td>{row.value}</td> + {row.link ? ( + <td> + <Link to={row.link}>{row.value}</Link> + </td> + ) : ( + <td>{row.value}</td> + )} </tr> ))} </tbody> diff --git a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx index 464328c665..f62b1cade1 100644 --- a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx +++ b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx @@ -14,6 +14,8 @@ interface PageHeaderProps { buttonLabel?: string; buttonVariant?: "primary" | "secondary" | "danger"; buttonTo?: string; + buttonIcon?: IconDefinition; + buttonOnClick?: () => void; } export default function PageHeader({ @@ -26,6 +28,8 @@ export default function PageHeader({ buttonLabel, buttonVariant = "primary", buttonTo, + buttonIcon, + buttonOnClick, }: PageHeaderProps) { const icon = ( <>{titleIcon && <FontAwesomeIcon icon={titleIcon} className="me-3" />}</> @@ -44,9 +48,11 @@ export default function PageHeader({ <div className="d-none d-md-block"> {showButton && ( <Button + icon={buttonIcon} variant={buttonVariant} label={buttonLabel} to={buttonTo} + onClick={buttonOnClick} /> )} </div> diff --git a/packages/fakeyou.com/src/v2/view/pages/media/AudioComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/AudioComponent.tsx deleted file mode 100644 index dc2763baad..0000000000 --- a/packages/fakeyou.com/src/v2/view/pages/media/AudioComponent.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import MediaData from "./MediaDataTypes"; - -import React from "react"; - -interface AudioComponentProps { - mediaData: MediaData; -} - -const AudioComponent: React.FC<AudioComponentProps> = ({ mediaData }) => { - return ( - <div className="w-100"> - <audio className="w-100" controls> - <source src={mediaData.public_bucket_path} /> - Your browser does not support the audio element. - </audio> - </div> - ); -}; - -export default AudioComponent; diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx new file mode 100644 index 0000000000..38c09fae4a --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx @@ -0,0 +1,17 @@ +import MediaData from "./MediaDataTypes"; +import React from "react"; +import AudioPlayer from "./MediaAudioPlayer"; + +interface MediaAudioComponentProps { + mediaData: MediaData; +} + +export default function MediaAudioComponent({ + mediaData, +}: MediaAudioComponentProps) { + return ( + <div className="w-100"> + <AudioPlayer mediaData={mediaData} /> + </div> + ); +} diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx new file mode 100644 index 0000000000..958d05790b --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx @@ -0,0 +1,150 @@ +import React from "react"; +import WaveSurfer from "wavesurfer.js"; +import { useEffect, useState } from "react"; +import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faPlay, faPause } from "@fortawesome/pro-solid-svg-icons"; +import MediaData from "./MediaDataTypes"; + +enum PlaybackSpeed { + HALF, + NORMAL, + DOUBLE, +} + +interface MediaAudioPlayerProps { + mediaData: MediaData; +} + +export default function MediaAudioPlayer({ mediaData }: MediaAudioPlayerProps) { + let [isPlaying, setIsPlaying] = useState(false); + let [isRepeating, setIsRepeating] = useState(false); + let [playbackSpeed, setPlaybackSpeed] = useState(PlaybackSpeed.NORMAL); + let [waveSurfer, setWaveSurfer] = useState<WaveSurfer | null>(null); + + useEffect(() => { + const wavesurferInstance = WaveSurfer.create({ + container: "#waveform", // Previousy I used 'this.ref.current' and React.createRef() + height: 200, + + responsive: true, + waveColor: "#cbcbcb", + progressColor: "#fc8481", + cursorColor: "#fc6b68", + cursorWidth: 2, + normalize: false, + }); + + setWaveSurfer(wavesurferInstance); + }, []); + + useEffect(() => { + const audioLink = new BucketConfig().getGcsUrl( + mediaData.public_bucket_path + ); + if (waveSurfer) { + waveSurfer.load(audioLink); + } + }, [waveSurfer, mediaData]); + + useEffect(() => { + if (waveSurfer) { + waveSurfer.unAll(); // NB: Otherwise we keep reinstalling the hooks and cause chaos + waveSurfer.on("pause", () => { + setIsPlaying(waveSurfer!.isPlaying()); + }); + waveSurfer.on("play", () => { + setIsPlaying(waveSurfer!.isPlaying()); + }); + waveSurfer.on("finish", () => { + if (waveSurfer && isRepeating) { + waveSurfer!.play(); + } + }); + } + }, [waveSurfer, isRepeating]); + + const togglePlayPause = () => { + if (waveSurfer) { + waveSurfer.playPause(); + } + }; + + const toggleIsRepeating = () => { + setIsRepeating(!isRepeating); + }; + + const togglePlaybackSpeed = () => { + let nextSpeed = PlaybackSpeed.NORMAL; + switch (playbackSpeed) { + case PlaybackSpeed.NORMAL: + nextSpeed = PlaybackSpeed.DOUBLE; + waveSurfer!.setPlaybackRate(1.5); // Okay, so a lie... + break; + case PlaybackSpeed.DOUBLE: + nextSpeed = PlaybackSpeed.HALF; + waveSurfer!.setPlaybackRate(0.5); + break; + case PlaybackSpeed.HALF: + nextSpeed = PlaybackSpeed.NORMAL; + waveSurfer!.setPlaybackRate(1.0); + break; + } + setPlaybackSpeed(nextSpeed); + }; + + let playButtonText = ( + <> + <FontAwesomeIcon icon={faPlay} /> + </> + ); + if (isPlaying) { + playButtonText = ( + <> + <FontAwesomeIcon icon={faPause} /> + </> + ); + } + + let repeatButtonText = isRepeating ? "Repeat" : "NoRepeat"; + + let speedButtonText = "1x"; + switch (playbackSpeed) { + case PlaybackSpeed.NORMAL: + speedButtonText = "1x"; + break; + case PlaybackSpeed.DOUBLE: + speedButtonText = "2x"; + break; + case PlaybackSpeed.HALF: + speedButtonText = "1/2x"; + break; + } + + return ( + <div> + <div id="waveform"></div> + <div className="d-flex gap-4 flex-column justify-content-center align-items-center mt-4"> + <div className="d-flex gap-2"> + <button className="btn btn-primary" onClick={() => togglePlayPause()}> + {playButtonText} + </button> + + <button + className="btn btn-secondary" + onClick={() => toggleIsRepeating()} + > + {repeatButtonText} + </button> + + <button + className="btn btn-secondary" + onClick={() => togglePlaybackSpeed()} + > + {speedButtonText} + </button> + </div> + </div> + </div> + ); +} diff --git a/packages/fakeyou.com/src/v2/view/pages/media/ImageComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaImageComponent.tsx similarity index 55% rename from packages/fakeyou.com/src/v2/view/pages/media/ImageComponent.tsx rename to packages/fakeyou.com/src/v2/view/pages/media/MediaImageComponent.tsx index e14dc65d51..4e55f75596 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/ImageComponent.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaImageComponent.tsx @@ -1,21 +1,21 @@ import React from "react"; import MediaData from "./MediaDataTypes"; -interface ImageComponentProps { +interface MediaImageComponentProps { mediaData: MediaData; } -const ImageComponent: React.FC<ImageComponentProps> = ({ mediaData }) => { +export default function MediaImageComponent({ + mediaData, +}: MediaImageComponentProps) { return ( <div> <img src={mediaData.public_bucket_path} - alt="test" // Make sure to provide alt text + alt="test" width="400" height="300" /> </div> ); -}; - -export default ImageComponent; +} diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 4a6e111a3b..ca26156f1b 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -1,8 +1,8 @@ import React, { useEffect, useState } from "react"; import { Link, useParams } from "react-router-dom"; -import AudioComponent from "./AudioComponent"; -import VideoComponent from "./VideoComponent"; -import ImageComponent from "./ImageComponent"; +import MediaAudioComponent from "./MediaAudioComponent"; +import MediaVideoComponent from "./MediaVideoComponent"; +import MediaImageComponent from "./MediaImageComponent"; import MediaData from "./MediaDataTypes"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; import Container from "components/common/Container"; @@ -10,11 +10,16 @@ import Panel from "components/common/Panel"; import PageHeader from "components/layout/PageHeader"; import Skeleton from "components/common/Skeleton"; import Button from "components/common/Button"; -import { faCircleExclamation } from "@fortawesome/pro-solid-svg-icons"; +import { + faCircleExclamation, + faArrowDownToLine, +} from "@fortawesome/pro-solid-svg-icons"; import Accordion from "components/common/Accordion"; import DataTable from "components/common/DataTable"; import { Gravatar } from "@storyteller/components/src/elements/Gravatar"; import useTimeAgo from "hooks/useTimeAgo"; +// import { RatingButtons } from "v2/view/_common/ratings/RatingButtons"; +// import { RatingStats } from "v2/view/_common/ratings/RatingStats"; interface MediaPageProps { sessionWrapper: SessionWrapper; @@ -69,16 +74,16 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { function renderMediaComponent(data: MediaData) { switch (data.media_type) { case "audio": - return <AudioComponent mediaData={data} />; + return <MediaAudioComponent mediaData={data} />; case "video": return ( <div className="ratio ratio-16x9"> - <VideoComponent mediaData={data} /> + <MediaVideoComponent mediaData={data} /> </div> ); case "image": - return <ImageComponent mediaData={data} />; + return <MediaImageComponent mediaData={data} />; default: return <div>Unsupported media type</div>; } @@ -124,29 +129,94 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </Container> ); - const mediaDetails = [ + const audioDetails = [ { property: "Type", value: mediaData.media_type }, { property: "Created at", value: mediaData.created_at }, { property: "Visibility", value: mediaData.creator_set_visibility }, + { + property: "Model", + value: mediaData.model_used, + link: mediaData.model_link, + }, + { + property: "Vocoder", + value: "Test", + }, + { + property: "Language", + value: mediaData.model_used, + }, { property: "Model", value: mediaData.model_used, }, ]; + const videoDetails = [ + { property: "Type", value: mediaData.media_type }, + { property: "Created at", value: mediaData.created_at }, + { property: "Visibility", value: mediaData.creator_set_visibility }, + ]; + + let pageTitle = "Result"; + let pageSubText = "This is the result of your media."; + let mediaDetails = undefined; + + switch (mediaData.media_type) { + case "audio": + pageTitle = "Audio Result"; + pageSubText = mediaData.token; + mediaDetails = ( + <Accordion.Item title="Audio Details" defaultOpen={true}> + <DataTable data={audioDetails} /> + </Accordion.Item> + ); + break; + case "video": + pageTitle = "Video Result"; + pageSubText = mediaData.token; + mediaDetails = ( + <Accordion.Item title="Video Details" defaultOpen={true}> + <DataTable data={videoDetails} /> + </Accordion.Item> + ); + break; + case "image": + pageTitle = "Image Model"; + pageSubText = "Image Model SubText"; + break; + default: + } + + // const resultRatings = ( + // <div className="d-flex flex-column flex-lg-row flex-column-reverse gap-3"> + // <div className="d-flex gap-3"> + // <RatingButtons entity_type="v2v_model" entity_token="test" /> + // </div> + // <RatingStats positive_votes={100} negative_votes={0} total_votes={100} /> + // </div> + // ); + return ( <Container type="panel"> - <PageHeader - title="Model name" - subText={mediaData.maybe_creator_user.display_name} - /> + <PageHeader title={pageTitle} subText={pageSubText} /> <Panel padding={true}> <div className="row g-4"> <div className="col-12 col-xl-8"> - {renderMediaComponent(mediaData)} + <div className="media-wrapper"> + {renderMediaComponent(mediaData)} + </div> </div> <div className="col-12 col-xl-4"> - <div className="d-flex mb-3 gap-2"> + <div className="d-flex mb-4"> + <Button + icon={faArrowDownToLine} + label="Download Result" + onClick={() => {}} + /> + </div> + <Accordion>{mediaDetails}</Accordion> + <div className="d-flex mt-4 gap-2"> <Gravatar size={48} username={mediaData.maybe_creator_user.display_name} @@ -167,11 +237,6 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { {timeCreated} </div> </div> - <Accordion> - <Accordion.Item title="Details" defaultOpen={true}> - <DataTable data={mediaDetails} /> - </Accordion.Item> - </Accordion> </div> </div> </Panel> diff --git a/packages/fakeyou.com/src/v2/view/pages/media/VideoComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaVideoComponent.tsx similarity index 70% rename from packages/fakeyou.com/src/v2/view/pages/media/VideoComponent.tsx rename to packages/fakeyou.com/src/v2/view/pages/media/MediaVideoComponent.tsx index 7cdd161ce4..313b4c72f5 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/VideoComponent.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaVideoComponent.tsx @@ -1,10 +1,13 @@ import React from "react"; import MediaData from "./MediaDataTypes"; -interface VideoComponentProps { + +interface MediaVideoComponentProps { mediaData: MediaData; } -export default function VideoComponent({ mediaData }: VideoComponentProps) { +export default function MediaVideoComponent({ + mediaData, +}: MediaVideoComponentProps) { return ( <video className="rounded" controls width="100%" height="auto"> <source src={mediaData.public_bucket_path} /> From c80f0648fe1026abe7d648589a99699734d6345f Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Mon, 16 Oct 2023 09:38:29 +0700 Subject: [PATCH 22/51] flex gap --- .../src/v2/view/pages/media/MediaPage.tsx | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index ca26156f1b..9960cdddc7 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -207,16 +207,8 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { {renderMediaComponent(mediaData)} </div> </div> - <div className="col-12 col-xl-4"> - <div className="d-flex mb-4"> - <Button - icon={faArrowDownToLine} - label="Download Result" - onClick={() => {}} - /> - </div> - <Accordion>{mediaDetails}</Accordion> - <div className="d-flex mt-4 gap-2"> + <div className="col-12 col-xl-4 d-flex flex-column gap-4"> + <div className="d-flex gap-2"> <Gravatar size={48} username={mediaData.maybe_creator_user.display_name} @@ -237,6 +229,16 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { {timeCreated} </div> </div> + + <Accordion>{mediaDetails}</Accordion> + + <div className="d-flex"> + <Button + icon={faArrowDownToLine} + label="Download Result" + onClick={() => {}} + /> + </div> </div> </div> </Panel> From 350022494886c2910d20851072e7ec2d1cfc88e9 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Mon, 16 Oct 2023 09:39:25 +0700 Subject: [PATCH 23/51] moved download to top --- packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 9960cdddc7..0b64c6023a 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -230,8 +230,6 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> </div> - <Accordion>{mediaDetails}</Accordion> - <div className="d-flex"> <Button icon={faArrowDownToLine} @@ -239,6 +237,8 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { onClick={() => {}} /> </div> + + <Accordion>{mediaDetails}</Accordion> </div> </div> </Panel> From d26baf129ecb8edc59996d45f381eafda16ce076 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Mon, 16 Oct 2023 14:03:39 +0700 Subject: [PATCH 24/51] more updates and comment section --- .../src/components/common/Button/Button.scss | 18 +++- .../src/components/common/Button/Button.tsx | 95 ++++++++++--------- .../fakeyou.com/src/scss/site-refresh.scss | 21 +++- .../view/pages/media/MediaAudioComponent.tsx | 4 +- .../src/v2/view/pages/media/MediaPage.tsx | 34 ++++++- yarn.lock | 2 +- 6 files changed, 113 insertions(+), 61 deletions(-) diff --git a/packages/fakeyou.com/src/components/common/Button/Button.scss b/packages/fakeyou.com/src/components/common/Button/Button.scss index 2b77945926..17ba047172 100644 --- a/packages/fakeyou.com/src/components/common/Button/Button.scss +++ b/packages/fakeyou.com/src/components/common/Button/Button.scss @@ -11,6 +11,16 @@ align-items: center; justify-content: center; color: $white !important; + + &-square { + width: 46.5px; + height: 46.5px; + } + + &-square-small { + width: 37.5px; + height: 37.5px; + } } .button-primary, @@ -45,9 +55,9 @@ border-color: lighten($secondary, 5%); } -.button-destructive, -.button-destructive:focus, -.button-destructive:active { +.button-danger, +.button-danger:focus, +.button-danger:active { background-color: $danger; color: $white !important; border: 2.5px solid; @@ -55,7 +65,7 @@ transition: 0.2s; } -.button-destructive:hover { +.button-danger:hover { background-color: lighten($danger, 5%); color: $white !important; border: 2.5px solid; diff --git a/packages/fakeyou.com/src/components/common/Button/Button.tsx b/packages/fakeyou.com/src/components/common/Button/Button.tsx index b67196aa13..cc68fe70a7 100644 --- a/packages/fakeyou.com/src/components/common/Button/Button.tsx +++ b/packages/fakeyou.com/src/components/common/Button/Button.tsx @@ -3,15 +3,20 @@ import { Link } from "react-router-dom"; import "./Button.scss"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; +import Tippy from "@tippyjs/react"; +import "tippy.js/dist/tippy.css"; interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { - label?: string; + label?: string | null; icon?: IconDefinition; small?: boolean; variant?: "primary" | "secondary" | "danger"; - to?: string; // for internal links - href?: string; // for external links + to?: string; + href?: string; target?: "_blank" | "_self"; + square?: boolean; + tooltip?: string; + full?: boolean; } export default function Button({ @@ -22,56 +27,52 @@ export default function Button({ to, href, target = "_self", + square, + tooltip, + full = false, ...rest }: ButtonProps) { - let buttonClass = `button`; + let IconComponent = icon ? ( + <FontAwesomeIcon icon={icon} className={!square && label ? "me-2" : ""} /> + ) : null; + let LabelComponent = !square ? label : null; - if (small) { - buttonClass += ` button-small`; - } + const externalClass = rest.className || ""; - switch (variant) { - case "primary": - buttonClass += " button-primary"; - break; - case "secondary": - buttonClass += " button-secondary"; - break; - case "danger": - buttonClass += " button-destructive"; - break; - default: - buttonClass += " button-primary"; - break; - } + const commonProps = { + className: `${externalClass} button ${small ? "button-small" : ""} ${ + square ? (small ? "button-square-small" : "button-square") : "" + } button-${variant} ${full ? "w-100" : ""}`, + }; - if (to) { - return ( - <Link to={to} className={buttonClass}> - {icon && <FontAwesomeIcon icon={icon} className="me-2" />} - {label} - </Link> - ); - } - if (href) { - return ( - <a - href={href} - target={target} - rel="noopener noreferrer" - className={buttonClass} - > - {icon && <FontAwesomeIcon icon={icon} className="me-2" />} - {label} - </a> - ); - } + delete rest.className; - // If neither 'to' nor 'href' are provided (regular button) - return ( - <button className={buttonClass} type="button" {...rest}> - {icon && <FontAwesomeIcon icon={icon} className="me-2" />} - {label} + const ButtonContent = ( + <> + {IconComponent} + {LabelComponent} + </> + ); + + const WrappedButton = to ? ( + <Link to={to} {...commonProps}> + {ButtonContent} + </Link> + ) : href ? ( + <a href={href} target={target} rel="noopener noreferrer" {...commonProps}> + {ButtonContent} + </a> + ) : ( + <button type="button" {...commonProps} {...rest}> + {ButtonContent} </button> ); + + return tooltip ? ( + <Tippy theme="fakeyou" content={tooltip}> + {WrappedButton} + </Tippy> + ) : ( + WrappedButton + ); } diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index 49acbb1051..b2b3462e19 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -926,10 +926,6 @@ styles with important tags: color: $white; } - .tippy-box[data-theme~="fakeyou"] > .tippy-svg-arrow { - fill: lighten($secondary, 5%); - } - .tippy-box[data-theme~="range-slider"] { margin-top: -5px; background-color: lighten($panel, 10%); @@ -937,6 +933,23 @@ styles with important tags: font-size: 13px !important; } + .tippy-box[data-theme~="fakeyou"][data-placement^="top"] + > .tippy-arrow::before { + border-top-color: lighten($secondary, 5%); + } + .tippy-box[data-theme~="fakeyou"][data-placement^="bottom"] + > .tippy-arrow::before { + border-bottom-color: lighten($secondary, 5%); + } + .tippy-box[data-theme~="fakeyou"][data-placement^="left"] + > .tippy-arrow::before { + border-left-color: lighten($secondary, 5%); + } + .tippy-box[data-theme~="fakeyou"][data-placement^="right"] + > .tippy-arrow::before { + border-right-color: lighten($secondary, 5%); + } + .sliding-content { overflow: hidden; opacity: 0; diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx index 38c09fae4a..3c4ca809e6 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx @@ -1,6 +1,6 @@ import MediaData from "./MediaDataTypes"; import React from "react"; -import AudioPlayer from "./MediaAudioPlayer"; +import MediaAudioPlayer from "./MediaAudioPlayer"; interface MediaAudioComponentProps { mediaData: MediaData; @@ -11,7 +11,7 @@ export default function MediaAudioComponent({ }: MediaAudioComponentProps) { return ( <div className="w-100"> - <AudioPlayer mediaData={mediaData} /> + <MediaAudioPlayer mediaData={mediaData} /> </div> ); } diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 0b64c6023a..7b2cbb258f 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -13,11 +13,14 @@ import Button from "components/common/Button"; import { faCircleExclamation, faArrowDownToLine, + faCirclePlay, + faShare, } from "@fortawesome/pro-solid-svg-icons"; import Accordion from "components/common/Accordion"; import DataTable from "components/common/DataTable"; import { Gravatar } from "@storyteller/components/src/elements/Gravatar"; import useTimeAgo from "hooks/useTimeAgo"; +import { CommentComponent } from "v2/view/_common/comments/CommentComponent"; // import { RatingButtons } from "v2/view/_common/ratings/RatingButtons"; // import { RatingStats } from "v2/view/_common/ratings/RatingStats"; @@ -28,7 +31,7 @@ interface MediaPageProps { // Dummy media data (replace with actual API data) let dummyMediaData = { token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", - media_type: "video", // Change to somthing like "video" or "image" to test different types + media_type: "audio", // Change to somthing like "video" or "image" to test different types public_bucket_path: "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.mp4", // Replace with actual URLs maybe_creator_user: { @@ -230,18 +233,43 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> </div> - <div className="d-flex"> + <div className="d-flex gap-2 flex-wrap"> <Button icon={faArrowDownToLine} - label="Download Result" + label="Download" onClick={() => {}} + className="flex-grow-1" /> + <div className="d-flex gap-2"> + <Button + square={true} + variant="secondary" + icon={faCirclePlay} + onClick={() => {}} + tooltip="Create" + /> + <Button + square={true} + variant="secondary" + icon={faShare} + onClick={() => {}} + tooltip="Share" + /> + </div> </div> <Accordion>{mediaDetails}</Accordion> </div> </div> </Panel> + <Panel padding={true} mt={true}> + <h4 className="mb-3">Comments</h4> + <CommentComponent + entityType="user" + entityToken={mediaData.token} + sessionWrapper={sessionWrapper} + /> + </Panel> </Container> ); } diff --git a/yarn.lock b/yarn.lock index 16f51c2909..12b7c816ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4442,7 +4442,7 @@ __metadata: axios: ^0.21.0 bulma: ^0.9.0 craco: ^0.0.3 - date-fns: ^2.22.1 + date-fns: 2.22.1 framer-motion: ^6.5.1 howler: ^2.2.0 i18next: ^21.6.11 From baa5d87adce8c28e62ddc7134ce2e97c15533950 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Mon, 16 Oct 2023 14:38:32 +0700 Subject: [PATCH 25/51] audio text addition --- .../src/v2/view/pages/media/MediaDataTypes.ts | 1 + .../src/v2/view/pages/media/MediaPage.tsx | 30 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts b/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts index 97148a2014..d262485b3b 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts @@ -12,6 +12,7 @@ export default interface MediaData { color_index: number; }; }; + audio_text: string; model_used: string; model_link: string; creator_set_visibility: string; diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 7b2cbb258f..c8361415cd 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -10,11 +10,13 @@ import Panel from "components/common/Panel"; import PageHeader from "components/layout/PageHeader"; import Skeleton from "components/common/Skeleton"; import Button from "components/common/Button"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCircleExclamation, faArrowDownToLine, faCirclePlay, faShare, + faSquareQuote, } from "@fortawesome/pro-solid-svg-icons"; import Accordion from "components/common/Accordion"; import DataTable from "components/common/DataTable"; @@ -45,6 +47,8 @@ let dummyMediaData = { }, }, model_used: "Ash Ketchum", + audio_text: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", model_link: "/tts/TM:6g1mfb9b6fb8", creator_set_visibility: "public", created_at: "2023-05-12T07:49:53Z", @@ -77,7 +81,18 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { function renderMediaComponent(data: MediaData) { switch (data.media_type) { case "audio": - return <MediaAudioComponent mediaData={data} />; + return ( + <div className="d-flex flex-column gap-4"> + <MediaAudioComponent mediaData={data} /> + <div> + <h5 className="fw-semibold"> + <FontAwesomeIcon icon={faSquareQuote} className="me-2" /> + Audio Text + </h5> + <p className="pb-3">{mediaData?.audio_text}</p> + </div> + </div> + ); case "video": return ( <div className="ratio ratio-16x9"> @@ -99,7 +114,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { title={<Skeleton type="medium" />} subText={<Skeleton type="short" />} /> - <Panel padding={true}> + <Panel padding={true} mb={true}> <div className="row"> <div className="col-12 col-xl-8"> <h1 className="mb-0"> @@ -113,6 +128,11 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> </div> </Panel> + <Panel padding={true}> + <h1 className="mb-0"> + <Skeleton /> + </h1> + </Panel> </Container> ); @@ -147,7 +167,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { }, { property: "Language", - value: mediaData.model_used, + value: "English", }, { property: "Model", @@ -262,8 +282,8 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> </div> </Panel> - <Panel padding={true} mt={true}> - <h4 className="mb-3">Comments</h4> + <Panel padding={true} mt={true} mb={true}> + <h4 className="fw-semibold mb-3">Comments</h4> <CommentComponent entityType="user" entityToken={mediaData.token} From fa39450f344e8f0d14306df0420b8895d43b5a4b Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Mon, 16 Oct 2023 14:39:59 +0700 Subject: [PATCH 26/51] set dummy data to video --- packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index c8361415cd..266f628c5b 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -33,7 +33,7 @@ interface MediaPageProps { // Dummy media data (replace with actual API data) let dummyMediaData = { token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", - media_type: "audio", // Change to somthing like "video" or "image" to test different types + media_type: "video", // Change to somthing like "video" or "image" to test different types public_bucket_path: "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.mp4", // Replace with actual URLs maybe_creator_user: { From b5d32df31b938f2597583dd846f50b3b5bdbcd81 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Mon, 16 Oct 2023 15:05:28 +0700 Subject: [PATCH 27/51] added dummy moderator details --- .../src/v2/view/pages/media/MediaPage.tsx | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 266f628c5b..9a77a52473 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -211,6 +211,36 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { default: } + let modMediaDetails = undefined; + + const modDetails = [ + { property: "Model creator is banned", value: "good standing" }, + { + property: "Result creator is banned (if user)", + value: "good standing", + }, + { + property: "Result creator IP address", + value: "0.0.0.0", + }, + { + property: "Mod deleted at (UTC)", + value: "not deleted", + }, + { + property: "Result creator deleted at (UTC)", + value: "not deleted", + }, + ]; + + if (sessionWrapper.canBanUsers()) { + modMediaDetails = ( + <Accordion.Item title="Moderator Details" defaultOpen={false}> + <DataTable data={modDetails} /> + </Accordion.Item> + ); + } + // const resultRatings = ( // <div className="d-flex flex-column flex-lg-row flex-column-reverse gap-3"> // <div className="d-flex gap-3"> @@ -278,7 +308,10 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> </div> - <Accordion>{mediaDetails}</Accordion> + <Accordion> + {mediaDetails} + {modMediaDetails} + </Accordion> </div> </div> </Panel> From dc51b1ca1e11686c1b6a9b2d62edda9c8d0796d4 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Mon, 16 Oct 2023 23:33:07 +0700 Subject: [PATCH 28/51] mediadata interface update --- .../src/v2/view/pages/media/MediaDataTypes.ts | 12 ++++-- .../src/v2/view/pages/media/MediaPage.tsx | 40 +++++++++++-------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts b/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts index d262485b3b..a6d6befc5d 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts @@ -1,6 +1,12 @@ +export enum MediaType { + Audio = "audio", + Video = "video", + Image = "image", +} + export default interface MediaData { token: string; - media_type: string; + media_type: MediaType; public_bucket_path: string; maybe_creator_user: { user_token: string; @@ -16,6 +22,6 @@ export default interface MediaData { model_used: string; model_link: string; creator_set_visibility: string; - created_at: string; - updated_at: string; + created_at: Date; + updated_at: Date; } diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 9a77a52473..667e86bdcb 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -3,7 +3,7 @@ import { Link, useParams } from "react-router-dom"; import MediaAudioComponent from "./MediaAudioComponent"; import MediaVideoComponent from "./MediaVideoComponent"; import MediaImageComponent from "./MediaImageComponent"; -import MediaData from "./MediaDataTypes"; +import MediaData, { MediaType } from "./MediaDataTypes"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; import Container from "components/common/Container"; import Panel from "components/common/Panel"; @@ -33,7 +33,7 @@ interface MediaPageProps { // Dummy media data (replace with actual API data) let dummyMediaData = { token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", - media_type: "video", // Change to somthing like "video" or "image" to test different types + media_type: MediaType.Video, // Change to somthing like "video" or "image" to test different types public_bucket_path: "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.mp4", // Replace with actual URLs maybe_creator_user: { @@ -51,8 +51,8 @@ let dummyMediaData = { "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", model_link: "/tts/TM:6g1mfb9b6fb8", creator_set_visibility: "public", - created_at: "2023-05-12T07:49:53Z", - updated_at: "2023-05-12T07:49:53Z", + created_at: new Date("2023-05-12T07:49:53Z"), + updated_at: new Date("2023-05-12T07:49:53Z"), }; export default function MediaPage({ sessionWrapper }: MediaPageProps) { @@ -61,7 +61,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { const [isLoading, setIsLoading] = useState<boolean>(true); const [error, setError] = useState<boolean>(false); - const timeCreated = useTimeAgo(mediaData?.created_at || ""); + const timeCreated = useTimeAgo(mediaData?.created_at.toISOString() || ""); // Simulate API call useEffect(() => { @@ -80,7 +80,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { function renderMediaComponent(data: MediaData) { switch (data.media_type) { - case "audio": + case MediaType.Audio: return ( <div className="d-flex flex-column gap-4"> <MediaAudioComponent mediaData={data} /> @@ -89,18 +89,20 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { <FontAwesomeIcon icon={faSquareQuote} className="me-2" /> Audio Text </h5> - <p className="pb-3">{mediaData?.audio_text}</p> + <p className="pb-3"> + {mediaData?.audio_text && mediaData.audio_text} + </p> </div> </div> ); - case "video": + case MediaType.Video: return ( <div className="ratio ratio-16x9"> <MediaVideoComponent mediaData={data} /> </div> ); - case "image": + case MediaType.Image: return <MediaImageComponent mediaData={data} />; default: return <div>Unsupported media type</div>; @@ -154,8 +156,11 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { const audioDetails = [ { property: "Type", value: mediaData.media_type }, - { property: "Created at", value: mediaData.created_at }, - { property: "Visibility", value: mediaData.creator_set_visibility }, + { property: "Created at", value: mediaData.created_at.toString() }, + { + property: "Visibility", + value: mediaData.creator_set_visibility.toString(), + }, { property: "Model", value: mediaData.model_used, @@ -177,8 +182,11 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { const videoDetails = [ { property: "Type", value: mediaData.media_type }, - { property: "Created at", value: mediaData.created_at }, - { property: "Visibility", value: mediaData.creator_set_visibility }, + { property: "Created at", value: mediaData.created_at.toString() }, + { + property: "Visibility", + value: mediaData.creator_set_visibility.toString(), + }, ]; let pageTitle = "Result"; @@ -186,7 +194,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { let mediaDetails = undefined; switch (mediaData.media_type) { - case "audio": + case MediaType.Audio: pageTitle = "Audio Result"; pageSubText = mediaData.token; mediaDetails = ( @@ -195,7 +203,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </Accordion.Item> ); break; - case "video": + case MediaType.Video: pageTitle = "Video Result"; pageSubText = mediaData.token; mediaDetails = ( @@ -204,7 +212,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </Accordion.Item> ); break; - case "image": + case MediaType.Image: pageTitle = "Image Model"; pageSubText = "Image Model SubText"; break; From 099ffa4c76c9793772f37beca41818ab35451630 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Tue, 17 Oct 2023 06:48:24 +0700 Subject: [PATCH 29/51] bootstrap changes and updates --- packages/fakeyou.com/package.json | 1 + packages/fakeyou.com/src/App.tsx | 16 ++- packages/fakeyou.com/src/index.tsx | 48 ++++---- .../src/scss/custom-bootstrap.scss | 11 ++ .../fakeyou.com/src/scss/site-refresh.scss | 17 +-- .../src/v2/view/pages/media/MediaPage.tsx | 108 +++++++++++++----- yarn.lock | 11 +- 7 files changed, 142 insertions(+), 70 deletions(-) create mode 100644 packages/fakeyou.com/src/scss/custom-bootstrap.scss diff --git a/packages/fakeyou.com/package.json b/packages/fakeyou.com/package.json index a0849337e4..deacd02d14 100644 --- a/packages/fakeyou.com/package.json +++ b/packages/fakeyou.com/package.json @@ -32,6 +32,7 @@ "@types/react-dom": "^16.9.8", "axios": "^0.21.0", "bulma": "^0.9.0", + "bootstrap": "5.1.3", "craco": "^0.0.3", "date-fns": "2.22.1", "framer-motion": "^6.5.1", diff --git a/packages/fakeyou.com/src/App.tsx b/packages/fakeyou.com/src/App.tsx index 4380c46c10..e9216c3325 100644 --- a/packages/fakeyou.com/src/App.tsx +++ b/packages/fakeyou.com/src/App.tsx @@ -1,4 +1,5 @@ import "./AppNew.scss"; +import "scss/custom-bootstrap.scss"; import React from "react"; import { ApiConfig } from "@storyteller/components"; @@ -184,12 +185,15 @@ function newVocodes() { return discord || twitter || alphaCookie; } -function initInferenceJobsByCategoryMap() : Map<FrontendInferenceJobType, InferenceJob[]> { - let inferenceJobsByCategory = new Map(); - inferenceJobsByCategory.set(FrontendInferenceJobType.FaceAnimation, []); - inferenceJobsByCategory.set(FrontendInferenceJobType.TextToSpeech, []); - inferenceJobsByCategory.set(FrontendInferenceJobType.VoiceConversion, []); - return inferenceJobsByCategory; +function initInferenceJobsByCategoryMap(): Map< + FrontendInferenceJobType, + InferenceJob[] +> { + let inferenceJobsByCategory = new Map(); + inferenceJobsByCategory.set(FrontendInferenceJobType.FaceAnimation, []); + inferenceJobsByCategory.set(FrontendInferenceJobType.TextToSpeech, []); + inferenceJobsByCategory.set(FrontendInferenceJobType.VoiceConversion, []); + return inferenceJobsByCategory; } function isMacOs() { diff --git a/packages/fakeyou.com/src/index.tsx b/packages/fakeyou.com/src/index.tsx index 8741671386..94946a02b5 100644 --- a/packages/fakeyou.com/src/index.tsx +++ b/packages/fakeyou.com/src/index.tsx @@ -1,32 +1,40 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import * as serviceWorker from './serviceWorker'; -import AppTranslated from './AppTranslated'; +import React from "react"; +import ReactDOM from "react-dom"; +import * as serviceWorker from "./serviceWorker"; +import AppTranslated from "./AppTranslated"; -const IS_IOS : boolean = /iPad|iPhone|iPod/.test(navigator.platform || ""); +const IS_IOS: boolean = /iPad|iPhone|iPod/.test(navigator.platform || ""); const enableSpectrograms = !IS_IOS; -const flashVocodesNotice = new URLSearchParams(window.location.search).has('vocodes'); +const flashVocodesNotice = new URLSearchParams(window.location.search).has( + "vocodes" +); -const designSystemClass = 'fakeyou-refresh'; +const designSystemClass = "fakeyou-refresh"; -document.getElementsByTagName('html')[0].classList.add(designSystemClass); +document.getElementsByTagName("html")[0].classList.add(designSystemClass); // We can't include Bootstrap CSS along with Bulma since some of the class names conflict. // TODO(echelon): Once ported, statically move CSS to "index.html". -const bootstrapCss = document.createElement("link"); -bootstrapCss.setAttribute("rel", "stylesheet"); -bootstrapCss.setAttribute("crossorigin", "anonymous"); -bootstrapCss.setAttribute("integrity", "sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"); -bootstrapCss.setAttribute("href", "https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"); -document.getElementsByTagName("head")[0].appendChild(bootstrapCss); +// const bootstrapCss = document.createElement("link"); +// bootstrapCss.setAttribute("rel", "stylesheet"); +// bootstrapCss.setAttribute("crossorigin", "anonymous"); +// bootstrapCss.setAttribute("integrity", "sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"); +// bootstrapCss.setAttribute("href", "https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"); +// document.getElementsByTagName("head")[0].appendChild(bootstrapCss); const bootstrapJs = document.createElement("script"); bootstrapJs.setAttribute("rel", "stylesheet"); bootstrapJs.setAttribute("crossorigin", "anonymous"); -bootstrapJs.setAttribute("integrity", "sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"); -bootstrapJs.setAttribute("src", "https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"); +bootstrapJs.setAttribute( + "integrity", + "sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" +); +bootstrapJs.setAttribute( + "src", + "https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" +); document.getElementsByTagName("body")[0].appendChild(bootstrapJs); // NB: Posthog turned off for most users (anonymous users) due to cost. @@ -37,11 +45,11 @@ document.getElementsByTagName("body")[0].appendChild(bootstrapJs); ReactDOM.render( <React.StrictMode> <AppTranslated - enableSpectrograms={enableSpectrograms} - flashVocodesNotice={flashVocodesNotice} - /> + enableSpectrograms={enableSpectrograms} + flashVocodesNotice={flashVocodesNotice} + /> </React.StrictMode>, - document.getElementById('root') + document.getElementById("root") ); // If you want your app to work offline and load faster, you can change diff --git a/packages/fakeyou.com/src/scss/custom-bootstrap.scss b/packages/fakeyou.com/src/scss/custom-bootstrap.scss new file mode 100644 index 0000000000..af52e438e1 --- /dev/null +++ b/packages/fakeyou.com/src/scss/custom-bootstrap.scss @@ -0,0 +1,11 @@ +// Override the $spacers variable +$spacers: ( + 0: 0, + 1: 0.25rem, + 2: 0.5rem, + 3: 1rem, + 4: 1.75rem, + 5: 2rem, +); + +@import "~bootstrap/scss/bootstrap"; diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index b2b3462e19..bd95287c79 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -168,11 +168,6 @@ styles with important tags: padding-bottom: 0.4rem !important; } - .py-4 { - padding-top: 2rem !important; - padding-bottom: 2rem !important; - } - .lead { color: rgba($white, 0.8); font-size: 17px; @@ -288,6 +283,10 @@ styles with important tags: border-radius: 50px; } + .bg-panel { + background-color: lighten($panel, 1%); + } + .panel { position: relative; width: 100%; @@ -1481,10 +1480,6 @@ textarea { } } - .p-lg-4 { - padding: 2rem !important; - } - .lead { font-size: 18px; } @@ -1551,9 +1546,5 @@ textarea { height: 100%; border-radius: 0.5rem; } - - .p-md-4 { - padding: 2rem !important; - } } } diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 667e86bdcb..51c2a7f5f8 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -111,31 +111,61 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { if (isLoading) return ( - <Container type="panel"> - <PageHeader - title={<Skeleton type="medium" />} - subText={<Skeleton type="short" />} - /> - <Panel padding={true} mb={true}> - <div className="row"> + <> + <Container type="padded"> + <div className="pt-4 pb-4"> + <h2 className="fw-bold mb-1 pt-0 pt-lg-1"> + <Skeleton type="medium" /> + </h2> + <p className="mb-0"> + <Skeleton type="short" /> + </p> + </div> + </Container> + + <Container type="padded"> + <div className="row g-4"> <div className="col-12 col-xl-8"> + <div className="panel p-3 py-4 p-md-4"> + <h1 className="mb-0"> + <Skeleton /> + </h1> + </div> + + <div className="panel p-3 py-4 p-md-4 mt-4 d-none d-xl-block"> + <h4 className="fw-semibold mb-3"> + <Skeleton /> + </h4> + <h1> + <Skeleton /> + </h1> + </div> + </div> + <div className="col-12 col-xl-4 d-flex flex-column gap-2"> + <h1 className="mb-0"> + <Skeleton /> + </h1> <h1 className="mb-0"> <Skeleton /> </h1> - </div> - <div className="col-12 col-xl-4"> <h1 className="mb-0"> <Skeleton /> </h1> </div> </div> - </Panel> - <Panel padding={true}> - <h1 className="mb-0"> - <Skeleton /> - </h1> - </Panel> - </Container> + </Container> + + <div className="d-xl-none mt-4"> + <Panel padding> + <h4 className="fw-semibold mb-3"> + <Skeleton /> + </h4> + <h1 className="mb-0"> + <Skeleton /> + </h1> + </Panel> + </div> + </> ); if (error || !mediaData) @@ -259,14 +289,29 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { // ); return ( - <Container type="panel"> - <PageHeader title={pageTitle} subText={pageSubText} /> - <Panel padding={true}> + <> + <Container> + <div className="container py-5"> + <h2 className="fw-bold mb-1">{pageTitle}</h2> + <p className="mb-0">{pageSubText}</p> + </div> + </Container> + + <Container type="padded"> <div className="row g-4"> <div className="col-12 col-xl-8"> - <div className="media-wrapper"> + <div className="panel media-wrapper rounded"> {renderMediaComponent(mediaData)} </div> + + <div className="panel p-3 py-4 p-md-4 mt-4 d-none d-xl-block"> + <h4 className="fw-semibold mb-3">Comments</h4> + <CommentComponent + entityType="user" + entityToken={mediaData.token} + sessionWrapper={sessionWrapper} + /> + </div> </div> <div className="col-12 col-xl-4 d-flex flex-column gap-4"> <div className="d-flex gap-2"> @@ -322,15 +367,18 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </Accordion> </div> </div> - </Panel> - <Panel padding={true} mt={true} mb={true}> - <h4 className="fw-semibold mb-3">Comments</h4> - <CommentComponent - entityType="user" - entityToken={mediaData.token} - sessionWrapper={sessionWrapper} - /> - </Panel> - </Container> + </Container> + + <div className="d-xl-none mt-4"> + <Panel padding> + <h4 className="fw-semibold mb-3">Comments</h4> + <CommentComponent + entityType="user" + entityToken={mediaData.token} + sessionWrapper={sessionWrapper} + /> + </Panel> + </div> + </> ); } diff --git a/yarn.lock b/yarn.lock index 12b7c816ce..57d148974a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4569,8 +4569,8 @@ __metadata: resolution: "@storyteller/root@workspace:." dependencies: "@react-spring/types": ^9.7.3 + bootstrap: 5.1.3 craco: ^0.0.3 - date-fns: 2.22.1 lerna: ^4.0.0 yarn: ^1.22.19 languageName: unknown @@ -7281,6 +7281,15 @@ __metadata: languageName: node linkType: hard +"bootstrap@npm:5.1.3": + version: 5.1.3 + resolution: "bootstrap@npm:5.1.3" + peerDependencies: + "@popperjs/core": ^2.10.2 + checksum: 301b5ed872efba061104cf22ac93568e3837867fb5527ab9326a51510fb752bd4883e1d488225c8be72f86d9d3a55ef5b166aa7fa62c2fdd077c3f05b65752f8 + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" From 3abaeb5ff3e94aac549b1b296cea35bc0fb094da Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Tue, 17 Oct 2023 07:01:25 +0700 Subject: [PATCH 30/51] panel component update --- .../src/components/common/Panel/Panel.tsx | 13 ++++----- .../layout/PageHeader/PageHeader.tsx | 2 +- .../PageHeaderModelView.tsx | 2 +- .../src/v2/view/pages/media/MediaPage.tsx | 28 ++++++++++--------- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/packages/fakeyou.com/src/components/common/Panel/Panel.tsx b/packages/fakeyou.com/src/components/common/Panel/Panel.tsx index 25e1d4281e..7b2f6ef07b 100644 --- a/packages/fakeyou.com/src/components/common/Panel/Panel.tsx +++ b/packages/fakeyou.com/src/components/common/Panel/Panel.tsx @@ -5,18 +5,15 @@ interface PanelProps { padding?: boolean; mb?: boolean; mt?: boolean; - full?: boolean; } -export default function Panel({ children, padding, mb, mt, full }: PanelProps) { +export default function Panel({ children, padding, mb, mt }: PanelProps) { return ( - <div className={full ? "container-panel mw-100" : "container-panel"}> - <div - className={`panel ${padding ? "p-3 py-4 p-md-4" : ""} + <div + className={`panel rounded ${padding ? "p-3 py-4 p-md-4" : ""} ${mb ? "mb-4" : ""} ${mt ? "mt-4" : ""}`} - > - {children} - </div> + > + {children} </div> ); } diff --git a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx index f62b1cade1..2dfedb1d2c 100644 --- a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx +++ b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx @@ -37,7 +37,7 @@ export default function PageHeader({ return ( <div className="pt-3 pb-4 pt-lg-4"> - <Panel padding full={full}> + <Panel padding> <div className="d-flex flex-column gap-4"> <div> <div className="d-flex"> diff --git a/packages/fakeyou.com/src/components/layout/PageHeaderModelView/PageHeaderModelView.tsx b/packages/fakeyou.com/src/components/layout/PageHeaderModelView/PageHeaderModelView.tsx index 331e477565..871b610374 100644 --- a/packages/fakeyou.com/src/components/layout/PageHeaderModelView/PageHeaderModelView.tsx +++ b/packages/fakeyou.com/src/components/layout/PageHeaderModelView/PageHeaderModelView.tsx @@ -35,7 +35,7 @@ export default function PageHeaderModelView({ return ( <div className="pt-3 pb-4 pt-lg-4"> {view === "regular" && ( - <Panel padding full={full}> + <Panel padding> <div className="row gy-3"> <div className="col-12 col-lg-8"> <h2 className="fw-bold"> diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 51c2a7f5f8..293483ab78 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -33,7 +33,7 @@ interface MediaPageProps { // Dummy media data (replace with actual API data) let dummyMediaData = { token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", - media_type: MediaType.Video, // Change to somthing like "video" or "image" to test different types + media_type: MediaType.Audio, // Change to somthing like "video" or "image" to test different types public_bucket_path: "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.mp4", // Replace with actual URLs maybe_creator_user: { @@ -82,7 +82,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { switch (data.media_type) { case MediaType.Audio: return ( - <div className="d-flex flex-column gap-4"> + <div className="panel p-3 p-lg-4 d-flex flex-column gap-4 rounded"> <MediaAudioComponent mediaData={data} /> <div> <h5 className="fw-semibold"> @@ -97,7 +97,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { ); case MediaType.Video: return ( - <div className="ratio ratio-16x9"> + <div className="panel ratio ratio-16x9"> <MediaVideoComponent mediaData={data} /> </div> ); @@ -298,9 +298,9 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </Container> <Container type="padded"> - <div className="row g-4"> + <div className="row g-4 mb-4"> <div className="col-12 col-xl-8"> - <div className="panel media-wrapper rounded"> + <div className="media-wrapper"> {renderMediaComponent(mediaData)} </div> @@ -370,14 +370,16 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </Container> <div className="d-xl-none mt-4"> - <Panel padding> - <h4 className="fw-semibold mb-3">Comments</h4> - <CommentComponent - entityType="user" - entityToken={mediaData.token} - sessionWrapper={sessionWrapper} - /> - </Panel> + <Container type="padded"> + <Panel> + <h4 className="fw-semibold mb-3">Comments</h4> + <CommentComponent + entityType="user" + entityToken={mediaData.token} + sessionWrapper={sessionWrapper} + /> + </Panel> + </Container> </div> </> ); From 776fa078a0286490b5284262544056349aeef136 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Tue, 17 Oct 2023 07:04:43 +0700 Subject: [PATCH 31/51] padding added to comments --- packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 293483ab78..38919b74f2 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -369,9 +369,9 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> </Container> - <div className="d-xl-none mt-4"> + <div className="d-xl-none my-4"> <Container type="padded"> - <Panel> + <Panel padding={true}> <h4 className="fw-semibold mb-3">Comments</h4> <CommentComponent entityType="user" From 60f494db1bccd013a5793b610c93815437c42b23 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Tue, 17 Oct 2023 07:05:42 +0700 Subject: [PATCH 32/51] default dummy data to video --- packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 38919b74f2..aad467ce72 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -33,7 +33,7 @@ interface MediaPageProps { // Dummy media data (replace with actual API data) let dummyMediaData = { token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", - media_type: MediaType.Audio, // Change to somthing like "video" or "image" to test different types + media_type: MediaType.Video, // Change to somthing like "video" or "image" to test different types public_bucket_path: "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.mp4", // Replace with actual URLs maybe_creator_user: { From 7566d8760c79164fe9175f0d6e4c2dddfbf97dc1 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Tue, 17 Oct 2023 15:23:11 +0700 Subject: [PATCH 33/51] panel padding fixes --- .../fakeyou.com/src/scss/site-refresh.scss | 14 ++ .../src/v2/view/pages/media/MediaPage.tsx | 134 +++++++++--------- 2 files changed, 84 insertions(+), 64 deletions(-) diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index bd95287c79..8e90561738 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -299,6 +299,15 @@ styles with important tags: 0 10px 8px rgb(0 0 0 / 3%), 0 4px 4px rgb(0 0 0 / 2%), 0 2px 2px rgb(0 0 0 / 1%) !important; + &.panel-clear { + padding-left: 1rem; + padding-right: 1rem; + background-color: transparent; + border: none; + border-color: transparent !important; + box-shadow: none !important; + } + .panel-inner { background-color: lighten($panel, 4%); } @@ -1531,6 +1540,11 @@ textarea { .panel { border-radius: 0.5rem; + + &.panel-clear { + padding-left: 0rem; + padding-right: 0rem; + } } ul.patrons-list { diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index aad467ce72..6f5d974e22 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -97,8 +97,10 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { ); case MediaType.Video: return ( - <div className="panel ratio ratio-16x9"> - <MediaVideoComponent mediaData={data} /> + <div className="panel panel-clear"> + <div className="ratio ratio-16x9"> + <MediaVideoComponent mediaData={data} /> + </div> </div> ); @@ -297,74 +299,78 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> </Container> - <Container type="padded"> - <div className="row g-4 mb-4"> - <div className="col-12 col-xl-8"> - <div className="media-wrapper"> - {renderMediaComponent(mediaData)} - </div> - - <div className="panel p-3 py-4 p-md-4 mt-4 d-none d-xl-block"> - <h4 className="fw-semibold mb-3">Comments</h4> - <CommentComponent - entityType="user" - entityToken={mediaData.token} - sessionWrapper={sessionWrapper} - /> - </div> - </div> - <div className="col-12 col-xl-4 d-flex flex-column gap-4"> - <div className="d-flex gap-2"> - <Gravatar - size={48} - username={mediaData.maybe_creator_user.display_name} - avatarIndex={ - mediaData.maybe_creator_user.default_avatar.image_index - } - backgroundIndex={ - mediaData.maybe_creator_user.default_avatar.color_index - } - /> - <div className="d-flex flex-column"> - <Link - className="fw-medium" - to={`/profile/${mediaData.maybe_creator_user.display_name}`} - > - {mediaData.maybe_creator_user.display_name} - </Link> - {timeCreated} + <Container type="panel"> + <div className="container-panel"> + <div className="row g-4 mb-4"> + <div className="col-12 col-xl-8"> + <div className="media-wrapper"> + {renderMediaComponent(mediaData)} </div> - </div> - <div className="d-flex gap-2 flex-wrap"> - <Button - icon={faArrowDownToLine} - label="Download" - onClick={() => {}} - className="flex-grow-1" - /> - <div className="d-flex gap-2"> - <Button - square={true} - variant="secondary" - icon={faCirclePlay} - onClick={() => {}} - tooltip="Create" - /> - <Button - square={true} - variant="secondary" - icon={faShare} - onClick={() => {}} - tooltip="Share" + <div className="panel p-3 py-4 p-md-4 mt-4 d-none d-xl-block"> + <h4 className="fw-semibold mb-3">Comments</h4> + <CommentComponent + entityType="user" + entityToken={mediaData.token} + sessionWrapper={sessionWrapper} /> </div> </div> + <div className="col-12 col-xl-4"> + <div className="panel panel-clear d-flex flex-column gap-4"> + <div className="d-flex gap-2"> + <Gravatar + size={48} + username={mediaData.maybe_creator_user.display_name} + avatarIndex={ + mediaData.maybe_creator_user.default_avatar.image_index + } + backgroundIndex={ + mediaData.maybe_creator_user.default_avatar.color_index + } + /> + <div className="d-flex flex-column"> + <Link + className="fw-medium" + to={`/profile/${mediaData.maybe_creator_user.display_name}`} + > + {mediaData.maybe_creator_user.display_name} + </Link> + {timeCreated} + </div> + </div> - <Accordion> - {mediaDetails} - {modMediaDetails} - </Accordion> + <div className="d-flex gap-2 flex-wrap"> + <Button + icon={faArrowDownToLine} + label="Download" + onClick={() => {}} + className="flex-grow-1" + /> + <div className="d-flex gap-2"> + <Button + square={true} + variant="secondary" + icon={faCirclePlay} + onClick={() => {}} + tooltip="Create" + /> + <Button + square={true} + variant="secondary" + icon={faShare} + onClick={() => {}} + tooltip="Share" + /> + </div> + </div> + + <Accordion> + {mediaDetails} + {modMediaDetails} + </Accordion> + </div> + </div> </div> </div> </Container> From 39ff6f036dcb6d9195e46fbf9968865a78044a11 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Tue, 17 Oct 2023 15:28:32 +0700 Subject: [PATCH 34/51] comments padding --- packages/fakeyou.com/src/components/common/Panel/Panel.tsx | 2 +- packages/fakeyou.com/src/scss/site-refresh.scss | 1 + packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/fakeyou.com/src/components/common/Panel/Panel.tsx b/packages/fakeyou.com/src/components/common/Panel/Panel.tsx index 7b2f6ef07b..f86e65d2f9 100644 --- a/packages/fakeyou.com/src/components/common/Panel/Panel.tsx +++ b/packages/fakeyou.com/src/components/common/Panel/Panel.tsx @@ -10,7 +10,7 @@ interface PanelProps { export default function Panel({ children, padding, mb, mt }: PanelProps) { return ( <div - className={`panel rounded ${padding ? "p-3 py-4 p-md-4" : ""} + className={`panel ${padding ? "p-3 py-4 p-md-4" : ""} ${mb ? "mb-4" : ""} ${mt ? "mt-4" : ""}`} > {children} diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index 8e90561738..6f5f04790b 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -1540,6 +1540,7 @@ textarea { .panel { border-radius: 0.5rem; + border: 0px !important; &.panel-clear { padding-left: 0rem; diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 6f5d974e22..3c33401482 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -376,7 +376,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </Container> <div className="d-xl-none my-4"> - <Container type="padded"> + <Container type="panel"> <Panel padding={true}> <h4 className="fw-semibold mb-3">Comments</h4> <CommentComponent From 099bb8d7b9b7e939cfcb3de90988bb4fd604b399 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Tue, 17 Oct 2023 15:46:58 +0700 Subject: [PATCH 35/51] panel border css --- packages/fakeyou.com/src/scss/site-refresh.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index 6f5f04790b..da4780ee4c 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -293,6 +293,8 @@ styles with important tags: background-color: $panel; border-color: #ffffff12 !important; border: 1px solid; + border-left: none; + border-right: none; border-radius: 0px; box-shadow: 0 0 0 1px rgba(0 0 0 / 16%), 0 70px 65px rgb(0 0 0 / 8%), 0 30px 30px rgb(0 0 0 / 7%), 0 15px 15px rgb(0 0 0 / 5%), @@ -1540,7 +1542,7 @@ textarea { .panel { border-radius: 0.5rem; - border: 0px !important; + border: 1px solid; &.panel-clear { padding-left: 0rem; From f7b05c3f7698c50bdacbc76f3f764e71816db7b9 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Tue, 17 Oct 2023 23:02:16 +0700 Subject: [PATCH 36/51] container panel update --- .../components/common/Container/Container.tsx | 11 +- .../src/v2/view/pages/media/MediaPage.tsx | 159 ++++++++---------- 2 files changed, 79 insertions(+), 91 deletions(-) diff --git a/packages/fakeyou.com/src/components/common/Container/Container.tsx b/packages/fakeyou.com/src/components/common/Container/Container.tsx index a8ae3ca28e..965c52dff4 100644 --- a/packages/fakeyou.com/src/components/common/Container/Container.tsx +++ b/packages/fakeyou.com/src/components/common/Container/Container.tsx @@ -3,11 +3,13 @@ import React from "react"; interface ContainerProps { children: React.ReactNode; type?: "full" | "padded" | "panel"; + className?: string; } export default function PageContainer({ children, - type = "panel", + type = "full", + className = "", }: ContainerProps) { let containerClass = ""; @@ -19,12 +21,15 @@ export default function PageContainer({ containerClass = "container"; break; case "panel": - containerClass = ""; + containerClass = "container-panel"; break; default: containerClass = "container-fluid"; break; } - return <div className={containerClass}>{children}</div>; + // Merge the classNames + const mergedClassNames = `${containerClass} ${className}`; + + return <div className={mergedClassNames}>{children}</div>; } diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 3c33401482..3aeaceb770 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -23,8 +23,6 @@ import DataTable from "components/common/DataTable"; import { Gravatar } from "@storyteller/components/src/elements/Gravatar"; import useTimeAgo from "hooks/useTimeAgo"; import { CommentComponent } from "v2/view/_common/comments/CommentComponent"; -// import { RatingButtons } from "v2/view/_common/ratings/RatingButtons"; -// import { RatingStats } from "v2/view/_common/ratings/RatingStats"; interface MediaPageProps { sessionWrapper: SessionWrapper; @@ -32,7 +30,7 @@ interface MediaPageProps { // Dummy media data (replace with actual API data) let dummyMediaData = { - token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", + token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", //-----access view at /media/m_v032bt6ecm0rwhebbhgdmk5rexf7cij to view this media media_type: MediaType.Video, // Change to somthing like "video" or "image" to test different types public_bucket_path: "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.mp4", // Replace with actual URLs @@ -89,9 +87,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { <FontAwesomeIcon icon={faSquareQuote} className="me-2" /> Audio Text </h5> - <p className="pb-3"> - {mediaData?.audio_text && mediaData.audio_text} - </p> + <p>{mediaData?.audio_text && mediaData.audio_text}</p> </div> </div> ); @@ -117,10 +113,10 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { <Container type="padded"> <div className="pt-4 pb-4"> <h2 className="fw-bold mb-1 pt-0 pt-lg-1"> - <Skeleton type="medium" /> + <Skeleton type="short" /> </h2> <p className="mb-0"> - <Skeleton type="short" /> + <Skeleton type="medium" /> </p> </div> </Container> @@ -281,95 +277,82 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { ); } - // const resultRatings = ( - // <div className="d-flex flex-column flex-lg-row flex-column-reverse gap-3"> - // <div className="d-flex gap-3"> - // <RatingButtons entity_type="v2v_model" entity_token="test" /> - // </div> - // <RatingStats positive_votes={100} negative_votes={0} total_votes={100} /> - // </div> - // ); - return ( <> - <Container> - <div className="container py-5"> - <h2 className="fw-bold mb-1">{pageTitle}</h2> - <p className="mb-0">{pageSubText}</p> - </div> + <Container type="padded" className="py-5"> + <h2 className="fw-bold mb-1">{pageTitle}</h2> + <p className="mb-0">{pageSubText}</p> </Container> <Container type="panel"> - <div className="container-panel"> - <div className="row g-4 mb-4"> - <div className="col-12 col-xl-8"> - <div className="media-wrapper"> - {renderMediaComponent(mediaData)} - </div> - - <div className="panel p-3 py-4 p-md-4 mt-4 d-none d-xl-block"> - <h4 className="fw-semibold mb-3">Comments</h4> - <CommentComponent - entityType="user" - entityToken={mediaData.token} - sessionWrapper={sessionWrapper} - /> - </div> + <div className="row g-4 mb-4"> + <div className="col-12 col-xl-8"> + <div className="media-wrapper"> + {renderMediaComponent(mediaData)} </div> - <div className="col-12 col-xl-4"> - <div className="panel panel-clear d-flex flex-column gap-4"> - <div className="d-flex gap-2"> - <Gravatar - size={48} - username={mediaData.maybe_creator_user.display_name} - avatarIndex={ - mediaData.maybe_creator_user.default_avatar.image_index - } - backgroundIndex={ - mediaData.maybe_creator_user.default_avatar.color_index - } - /> - <div className="d-flex flex-column"> - <Link - className="fw-medium" - to={`/profile/${mediaData.maybe_creator_user.display_name}`} - > - {mediaData.maybe_creator_user.display_name} - </Link> - {timeCreated} - </div> - </div> - <div className="d-flex gap-2 flex-wrap"> - <Button - icon={faArrowDownToLine} - label="Download" - onClick={() => {}} - className="flex-grow-1" - /> - <div className="d-flex gap-2"> - <Button - square={true} - variant="secondary" - icon={faCirclePlay} - onClick={() => {}} - tooltip="Create" - /> - <Button - square={true} - variant="secondary" - icon={faShare} - onClick={() => {}} - tooltip="Share" - /> - </div> + <div className="panel p-3 py-4 p-md-4 mt-4 d-none d-xl-block"> + <h4 className="fw-semibold mb-3">Comments</h4> + <CommentComponent + entityType="user" + entityToken={mediaData.token} + sessionWrapper={sessionWrapper} + /> + </div> + </div> + <div className="col-12 col-xl-4"> + <div className="panel panel-clear d-flex flex-column gap-4"> + <div className="d-flex gap-2"> + <Gravatar + size={48} + username={mediaData.maybe_creator_user.display_name} + avatarIndex={ + mediaData.maybe_creator_user.default_avatar.image_index + } + backgroundIndex={ + mediaData.maybe_creator_user.default_avatar.color_index + } + /> + <div className="d-flex flex-column"> + <Link + className="fw-medium" + to={`/profile/${mediaData.maybe_creator_user.display_name}`} + > + {mediaData.maybe_creator_user.display_name} + </Link> + {timeCreated} </div> - - <Accordion> - {mediaDetails} - {modMediaDetails} - </Accordion> </div> + + <div className="d-flex gap-2 flex-wrap"> + <Button + icon={faArrowDownToLine} + label="Download" + onClick={() => {}} + className="flex-grow-1" + /> + <div className="d-flex gap-2"> + <Button + square={true} + variant="secondary" + icon={faCirclePlay} + onClick={() => {}} + tooltip="Create" + /> + <Button + square={true} + variant="secondary" + icon={faShare} + onClick={() => {}} + tooltip="Share" + /> + </div> + </div> + + <Accordion> + {mediaDetails} + {modMediaDetails} + </Accordion> </div> </div> </div> From bd6bd3b284e94f70849de5a5a375b71d39bb3989 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Wed, 18 Oct 2023 10:07:46 +0700 Subject: [PATCH 37/51] skeleton length change --- packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 3aeaceb770..0c4be0b9d3 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -132,7 +132,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { <div className="panel p-3 py-4 p-md-4 mt-4 d-none d-xl-block"> <h4 className="fw-semibold mb-3"> - <Skeleton /> + <Skeleton type="short" /> </h4> <h1> <Skeleton /> @@ -141,7 +141,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> <div className="col-12 col-xl-4 d-flex flex-column gap-2"> <h1 className="mb-0"> - <Skeleton /> + <Skeleton type="medium" /> </h1> <h1 className="mb-0"> <Skeleton /> @@ -156,7 +156,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { <div className="d-xl-none mt-4"> <Panel padding> <h4 className="fw-semibold mb-3"> - <Skeleton /> + <Skeleton type="short" /> </h4> <h1 className="mb-0"> <Skeleton /> From 4f0079e715dc1e57bf93f9e92ae7e6bc5a68827e Mon Sep 17 00:00:00 2001 From: Brandon Thomas <echelon@gmail.com> Date: Wed, 18 Oct 2023 04:13:28 -0400 Subject: [PATCH 38/51] Hook up to API --- packages/components/src/api/ApiConfig.ts | 6 + .../src/api/_common/UserDetailsLight.ts | 17 +++ .../src/api/_common/enums/MediaFileType.ts | 6 + .../src/api/media_files/GetMediaFile.ts | 52 +++++++ packages/fakeyou.com/package.json | 2 +- .../view/pages/media/MediaAudioComponent.tsx | 8 +- .../v2/view/pages/media/MediaAudioPlayer.tsx | 10 +- .../src/v2/view/pages/media/MediaDataTypes.ts | 27 ---- .../view/pages/media/MediaImageComponent.tsx | 8 +- .../src/v2/view/pages/media/MediaPage.tsx | 130 +++++++----------- .../view/pages/media/MediaVideoComponent.tsx | 13 +- yarn.lock | 2 +- 12 files changed, 158 insertions(+), 123 deletions(-) create mode 100644 packages/components/src/api/_common/UserDetailsLight.ts create mode 100644 packages/components/src/api/_common/enums/MediaFileType.ts create mode 100644 packages/components/src/api/media_files/GetMediaFile.ts delete mode 100644 packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts diff --git a/packages/components/src/api/ApiConfig.ts b/packages/components/src/api/ApiConfig.ts index 459efd25f2..6c55b60b55 100644 --- a/packages/components/src/api/ApiConfig.ts +++ b/packages/components/src/api/ApiConfig.ts @@ -410,6 +410,12 @@ class ApiConfig { return `${this.getApiOrigin()}/voice_clone_requests/check`; } + // =============== Media Files =============== + + getMediaFile(mediaFileToken: string): string { + return `${this.getApiOrigin()}/v1/media_files/file/${mediaFileToken}`; + } + // =============== File Uploads =============== uploadAudio(): string { diff --git a/packages/components/src/api/_common/UserDetailsLight.ts b/packages/components/src/api/_common/UserDetailsLight.ts new file mode 100644 index 0000000000..a913fe44df --- /dev/null +++ b/packages/components/src/api/_common/UserDetailsLight.ts @@ -0,0 +1,17 @@ +/// A common type returned by several endpoints. +/// Basic information to display a user and their avatar. +export interface UserDetailsLight { + user_token: string, + /// Username (lowercase) + username: string, + /// Username with user-specified capitalization + display_name: string, + gravatar_hash: string, + default_avatar: DefaultAvatarInfo, + +} + +export interface DefaultAvatarInfo { + image_index: number, + color_index: number, +} diff --git a/packages/components/src/api/_common/enums/MediaFileType.ts b/packages/components/src/api/_common/enums/MediaFileType.ts new file mode 100644 index 0000000000..b104aeaa7b --- /dev/null +++ b/packages/components/src/api/_common/enums/MediaFileType.ts @@ -0,0 +1,6 @@ + +export enum MediaFileType { + Audio = "audio", + Video = "video", + Image = "image", +} diff --git a/packages/components/src/api/media_files/GetMediaFile.ts b/packages/components/src/api/media_files/GetMediaFile.ts new file mode 100644 index 0000000000..29bdc1a7fc --- /dev/null +++ b/packages/components/src/api/media_files/GetMediaFile.ts @@ -0,0 +1,52 @@ +import { ApiConfig } from "../ApiConfig"; +import { UserDetailsLight } from "../_common/UserDetailsLight"; +import { MediaFileType } from "../_common/enums/MediaFileType"; + +export interface MediaFile { + token: string, + media_type: MediaFileType, + public_bucket_path: string, + maybe_creator_user: UserDetailsLight | null, + creator_set_visibility: string, + created_at: Date, + updated_at: Date, +} + +export enum MediaFileLookupError { + NotFound, + ServerError, + FrontendError, +} + +export interface GetMediaFileResponse { + success: boolean, + media_file?: MediaFile, +} + +export async function GetMediaFile(mediaFileToken: string) : Promise<GetMediaFileResponse> { + const endpoint = new ApiConfig().getMediaFile(mediaFileToken); + + return await fetch(endpoint, { + method: 'GET', + headers: { + 'Accept': 'application/json', + }, + credentials: 'include', + }) + .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.updated_at = new Date(response.media_file.updated_at); + return response; + } else { + return { success : false }; + } + }) + .catch(e => { + return { success : false }; + }); +} diff --git a/packages/fakeyou.com/package.json b/packages/fakeyou.com/package.json index deacd02d14..3bd36b3497 100644 --- a/packages/fakeyou.com/package.json +++ b/packages/fakeyou.com/package.json @@ -31,8 +31,8 @@ "@types/react": "^16.9.36", "@types/react-dom": "^16.9.8", "axios": "^0.21.0", - "bulma": "^0.9.0", "bootstrap": "5.1.3", + "bulma": "^0.9.0", "craco": "^0.0.3", "date-fns": "2.22.1", "framer-motion": "^6.5.1", diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx index 3c4ca809e6..9feb2c8878 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioComponent.tsx @@ -1,17 +1,17 @@ -import MediaData from "./MediaDataTypes"; import React from "react"; import MediaAudioPlayer from "./MediaAudioPlayer"; +import { MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile"; interface MediaAudioComponentProps { - mediaData: MediaData; + mediaFile: MediaFile; } export default function MediaAudioComponent({ - mediaData, + mediaFile, }: MediaAudioComponentProps) { return ( <div className="w-100"> - <MediaAudioPlayer mediaData={mediaData} /> + <MediaAudioPlayer mediaFile={mediaFile} /> </div> ); } diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx index 958d05790b..4b5cd6481b 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from "react"; import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faPlay, faPause } from "@fortawesome/pro-solid-svg-icons"; -import MediaData from "./MediaDataTypes"; +import { MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile"; enum PlaybackSpeed { HALF, @@ -13,10 +13,10 @@ enum PlaybackSpeed { } interface MediaAudioPlayerProps { - mediaData: MediaData; + mediaFile: MediaFile; } -export default function MediaAudioPlayer({ mediaData }: MediaAudioPlayerProps) { +export default function MediaAudioPlayer({ mediaFile }: MediaAudioPlayerProps) { let [isPlaying, setIsPlaying] = useState(false); let [isRepeating, setIsRepeating] = useState(false); let [playbackSpeed, setPlaybackSpeed] = useState(PlaybackSpeed.NORMAL); @@ -40,12 +40,12 @@ export default function MediaAudioPlayer({ mediaData }: MediaAudioPlayerProps) { useEffect(() => { const audioLink = new BucketConfig().getGcsUrl( - mediaData.public_bucket_path + mediaFile.public_bucket_path ); if (waveSurfer) { waveSurfer.load(audioLink); } - }, [waveSurfer, mediaData]); + }, [waveSurfer, mediaFile]); useEffect(() => { if (waveSurfer) { diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts b/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts deleted file mode 100644 index a6d6befc5d..0000000000 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaDataTypes.ts +++ /dev/null @@ -1,27 +0,0 @@ -export enum MediaType { - Audio = "audio", - Video = "video", - Image = "image", -} - -export default interface MediaData { - token: string; - media_type: MediaType; - public_bucket_path: string; - maybe_creator_user: { - user_token: string; - username: string; - display_name: string; - gravatar_hash: string; - default_avatar: { - image_index: number; - color_index: number; - }; - }; - audio_text: string; - model_used: string; - model_link: string; - creator_set_visibility: string; - created_at: Date; - updated_at: Date; -} diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaImageComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaImageComponent.tsx index 4e55f75596..b09ee77ac3 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaImageComponent.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaImageComponent.tsx @@ -1,17 +1,17 @@ +import { MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile"; import React from "react"; -import MediaData from "./MediaDataTypes"; interface MediaImageComponentProps { - mediaData: MediaData; + mediaFile: MediaFile; } export default function MediaImageComponent({ - mediaData, + mediaFile, }: MediaImageComponentProps) { return ( <div> <img - src={mediaData.public_bucket_path} + src={mediaFile.public_bucket_path} alt="test" width="400" height="300" diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 0c4be0b9d3..6cd7a1b11c 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -1,10 +1,10 @@ -import React, { useEffect, useState } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import { Link, useParams } from "react-router-dom"; import MediaAudioComponent from "./MediaAudioComponent"; import MediaVideoComponent from "./MediaVideoComponent"; import MediaImageComponent from "./MediaImageComponent"; -import MediaData, { MediaType } from "./MediaDataTypes"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; +import { GetMediaFile, MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile"; import Container from "components/common/Container"; import Panel from "components/common/Panel"; import PageHeader from "components/layout/PageHeader"; @@ -23,85 +23,61 @@ import DataTable from "components/common/DataTable"; import { Gravatar } from "@storyteller/components/src/elements/Gravatar"; import useTimeAgo from "hooks/useTimeAgo"; import { CommentComponent } from "v2/view/_common/comments/CommentComponent"; +import { MediaFileType } from "@storyteller/components/src/api/_common/enums/MediaFileType"; interface MediaPageProps { sessionWrapper: SessionWrapper; } -// Dummy media data (replace with actual API data) -let dummyMediaData = { - token: "m_v032bt6ecm0rwhebbhgdmk5rexf7cij", //-----access view at /media/m_v032bt6ecm0rwhebbhgdmk5rexf7cij to view this media - media_type: MediaType.Video, // Change to somthing like "video" or "image" to test different types - public_bucket_path: - "/media/8/p/c/h/h/8pchhrgc0ayawn09s9gmtfec2mcft0xk/fakeyou_8pchhrgc0ayawn09s9gmtfec2mcft0xk.mp4", // Replace with actual URLs - maybe_creator_user: { - user_token: "u_00XGM6M2TE4J9", - username: "hanashi", - display_name: "Hanashi", - gravatar_hash: "c45b453fcb1d27b348504ae7f5d6a6c", - default_avatar: { - image_index: 1, - color_index: 3, - }, - }, - model_used: "Ash Ketchum", - audio_text: - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.", - model_link: "/tts/TM:6g1mfb9b6fb8", - creator_set_visibility: "public", - created_at: new Date("2023-05-12T07:49:53Z"), - updated_at: new Date("2023-05-12T07:49:53Z"), -}; - export default function MediaPage({ sessionWrapper }: MediaPageProps) { const { token } = useParams<{ token: string }>(); - const [mediaData, setMediaData] = useState<MediaData | null>(null); + const [mediaFile, setMediaFile] = useState<MediaFile | undefined | null>(null); const [isLoading, setIsLoading] = useState<boolean>(true); const [error, setError] = useState<boolean>(false); - const timeCreated = useTimeAgo(mediaData?.created_at.toISOString() || ""); + const timeCreated = useTimeAgo(mediaFile?.created_at.toISOString() || ""); + + const getMediaFile = useCallback(async (mediaFileToken: string) => { + let result = await GetMediaFile(mediaFileToken); + if (result.media_file) { + setMediaFile(result.media_file); + setIsLoading(false); + } else { + setError(true); + setIsLoading(false); + } + }, []); - // Simulate API call useEffect(() => { - setTimeout(() => { - //Check if token is valid - if (token !== dummyMediaData.token) { - //if invalid token, set error to true - setError(true); - setIsLoading(false); - } else { - setMediaData(dummyMediaData); - setIsLoading(false); - } - }, 1000); - }, [token]); + getMediaFile(token); + }, [token, getMediaFile]); - function renderMediaComponent(data: MediaData) { - switch (data.media_type) { - case MediaType.Audio: + function renderMediaComponent(mediaFile: MediaFile) { + switch (mediaFile.media_type) { + case MediaFileType.Audio: return ( <div className="panel p-3 p-lg-4 d-flex flex-column gap-4 rounded"> - <MediaAudioComponent mediaData={data} /> + <MediaAudioComponent mediaFile={mediaFile} /> <div> <h5 className="fw-semibold"> <FontAwesomeIcon icon={faSquareQuote} className="me-2" /> Audio Text </h5> - <p>{mediaData?.audio_text && mediaData.audio_text}</p> + {/*<p>{mediaFile?.audio_text && mediaFile.audio_text}</p>*/} </div> </div> ); - case MediaType.Video: + case MediaFileType.Video: return ( <div className="panel panel-clear"> <div className="ratio ratio-16x9"> - <MediaVideoComponent mediaData={data} /> + <MediaVideoComponent mediaFile={mediaFile} /> </div> </div> ); - case MediaType.Image: - return <MediaImageComponent mediaData={data} />; + case MediaFileType.Image: + return <MediaImageComponent mediaFile={mediaFile} />; default: return <div>Unsupported media type</div>; } @@ -166,7 +142,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </> ); - if (error || !mediaData) + if (error || !mediaFile) return ( <Container type="panel"> <PageHeader @@ -183,16 +159,16 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { ); const audioDetails = [ - { property: "Type", value: mediaData.media_type }, - { property: "Created at", value: mediaData.created_at.toString() }, + { property: "Type", value: mediaFile.media_type }, + { property: "Created at", value: mediaFile.created_at.toString() }, { property: "Visibility", - value: mediaData.creator_set_visibility.toString(), + value: mediaFile.creator_set_visibility.toString(), }, - { + /*{ property: "Model", - value: mediaData.model_used, - link: mediaData.model_link, + value: mediaFile.model_used, + link: mediaFile.model_link, }, { property: "Vocoder", @@ -204,16 +180,16 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { }, { property: "Model", - value: mediaData.model_used, - }, + value: mediaFile.model_used, + },*/ ]; const videoDetails = [ - { property: "Type", value: mediaData.media_type }, - { property: "Created at", value: mediaData.created_at.toString() }, + { property: "Type", value: mediaFile.media_type }, + { property: "Created at", value: mediaFile.created_at.toString() }, { property: "Visibility", - value: mediaData.creator_set_visibility.toString(), + value: mediaFile.creator_set_visibility.toString(), }, ]; @@ -221,26 +197,26 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { let pageSubText = "This is the result of your media."; let mediaDetails = undefined; - switch (mediaData.media_type) { - case MediaType.Audio: + switch (mediaFile.media_type) { + case MediaFileType.Audio: pageTitle = "Audio Result"; - pageSubText = mediaData.token; + pageSubText = mediaFile.token; mediaDetails = ( <Accordion.Item title="Audio Details" defaultOpen={true}> <DataTable data={audioDetails} /> </Accordion.Item> ); break; - case MediaType.Video: + case MediaFileType.Video: pageTitle = "Video Result"; - pageSubText = mediaData.token; + pageSubText = mediaFile.token; mediaDetails = ( <Accordion.Item title="Video Details" defaultOpen={true}> <DataTable data={videoDetails} /> </Accordion.Item> ); break; - case MediaType.Image: + case MediaFileType.Image: pageTitle = "Image Model"; pageSubText = "Image Model SubText"; break; @@ -288,14 +264,14 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { <div className="row g-4 mb-4"> <div className="col-12 col-xl-8"> <div className="media-wrapper"> - {renderMediaComponent(mediaData)} + {renderMediaComponent(mediaFile)} </div> <div className="panel p-3 py-4 p-md-4 mt-4 d-none d-xl-block"> <h4 className="fw-semibold mb-3">Comments</h4> <CommentComponent entityType="user" - entityToken={mediaData.token} + entityToken={mediaFile.token} sessionWrapper={sessionWrapper} /> </div> @@ -305,20 +281,20 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { <div className="d-flex gap-2"> <Gravatar size={48} - username={mediaData.maybe_creator_user.display_name} + username={mediaFile.maybe_creator_user?.display_name} avatarIndex={ - mediaData.maybe_creator_user.default_avatar.image_index + mediaFile.maybe_creator_user?.default_avatar.image_index } backgroundIndex={ - mediaData.maybe_creator_user.default_avatar.color_index + mediaFile.maybe_creator_user?.default_avatar.color_index } /> <div className="d-flex flex-column"> <Link className="fw-medium" - to={`/profile/${mediaData.maybe_creator_user.display_name}`} + to={`/profile/${mediaFile.maybe_creator_user?.display_name}`} > - {mediaData.maybe_creator_user.display_name} + {mediaFile.maybe_creator_user?.display_name} </Link> {timeCreated} </div> @@ -364,7 +340,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { <h4 className="fw-semibold mb-3">Comments</h4> <CommentComponent entityType="user" - entityToken={mediaData.token} + entityToken={mediaFile.token} sessionWrapper={sessionWrapper} /> </Panel> diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaVideoComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaVideoComponent.tsx index 313b4c72f5..786de72de2 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaVideoComponent.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaVideoComponent.tsx @@ -1,16 +1,21 @@ +import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; +import { MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile"; import React from "react"; -import MediaData from "./MediaDataTypes"; interface MediaVideoComponentProps { - mediaData: MediaData; + mediaFile: MediaFile; } export default function MediaVideoComponent({ - mediaData, + mediaFile, }: MediaVideoComponentProps) { + let mediaLink = new BucketConfig().getGcsUrl( + mediaFile.public_bucket_path + ); + return ( <video className="rounded" controls width="100%" height="auto"> - <source src={mediaData.public_bucket_path} /> + <source src={mediaLink} /> Your browser does not support the video element. </video> ); diff --git a/yarn.lock b/yarn.lock index 57d148974a..38cea68bf5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4440,6 +4440,7 @@ __metadata: "@types/uuid": ^8.3.0 "@types/wavesurfer.js": ^5.2.0 axios: ^0.21.0 + bootstrap: 5.1.3 bulma: ^0.9.0 craco: ^0.0.3 date-fns: 2.22.1 @@ -4569,7 +4570,6 @@ __metadata: resolution: "@storyteller/root@workspace:." dependencies: "@react-spring/types": ^9.7.3 - bootstrap: 5.1.3 craco: ^0.0.3 lerna: ^4.0.0 yarn: ^1.22.19 From 80da5b0dad61687a63ba2129f46bc1ea4515de87 Mon Sep 17 00:00:00 2001 From: Brandon Thomas <echelon@gmail.com> Date: Wed, 18 Oct 2023 04:58:26 -0400 Subject: [PATCH 39/51] redirect for media --- _redirects | 1 + 1 file changed, 1 insertion(+) diff --git a/_redirects b/_redirects index 2c2c0c7c3b..cc890efa66 100644 --- a/_redirects +++ b/_redirects @@ -18,6 +18,7 @@ /landing_temp* /index.html 200 /leaderboard* /index.html 200 /login* /index.html 200 +/media* /index.html 200 /moderation* /index.html 200 /news* /index.html 200 /obs_configs* /index.html 200 From bafa779bfe406bc999d84aa4f7869e65aec90df0 Mon Sep 17 00:00:00 2001 From: Brandon Thomas <echelon@gmail.com> Date: Thu, 19 Oct 2023 03:21:45 -0400 Subject: [PATCH 40/51] move to calling user /v1 endpoints --- packages/components/src/api/ApiConfig.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/components/src/api/ApiConfig.ts b/packages/components/src/api/ApiConfig.ts index 6c55b60b55..018fac0aa2 100644 --- a/packages/components/src/api/ApiConfig.ts +++ b/packages/components/src/api/ApiConfig.ts @@ -96,19 +96,19 @@ class ApiConfig { } createAccount(): string { - return `${this.getApiOrigin()}/create_account`; + return `${this.getApiOrigin()}/v1/create_account`; } login(): string { - return `${this.getApiOrigin()}/login`; + return `${this.getApiOrigin()}/v1/login`; } logout(): string { - return `${this.getApiOrigin()}/logout`; + return `${this.getApiOrigin()}/v1/logout`; } sessionDetails(): string { - return `${this.getApiOrigin()}/session`; + return `${this.getApiOrigin()}/v1/session`; } getQueueStats(): string { From 1de1d0486ac1bcab5c9f7d0f6cc60b2d7323bcdb Mon Sep 17 00:00:00 2001 From: Brandon Thomas <echelon@gmail.com> Date: Thu, 19 Oct 2023 03:23:12 -0400 Subject: [PATCH 41/51] create account doesn't have a /v1 url yet --- packages/components/src/api/ApiConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/api/ApiConfig.ts b/packages/components/src/api/ApiConfig.ts index 018fac0aa2..649be9f3f4 100644 --- a/packages/components/src/api/ApiConfig.ts +++ b/packages/components/src/api/ApiConfig.ts @@ -96,7 +96,7 @@ class ApiConfig { } createAccount(): string { - return `${this.getApiOrigin()}/v1/create_account`; + return `${this.getApiOrigin()}/create_account`; } login(): string { From e0e6816596ff4588e457c9a2edf857670b193751 Mon Sep 17 00:00:00 2001 From: BFlat <bflat@storyteller.ai> Date: Fri, 20 Oct 2023 05:06:44 +0700 Subject: [PATCH 42/51] media page title removal (#310) * remove header title * update * commented out buttons for now --- .../src/v2/view/pages/media/MediaPage.tsx | 51 ++++++------------- 1 file changed, 16 insertions(+), 35 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 6cd7a1b11c..2ae398610a 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -4,7 +4,10 @@ import MediaAudioComponent from "./MediaAudioComponent"; import MediaVideoComponent from "./MediaVideoComponent"; import MediaImageComponent from "./MediaImageComponent"; import { SessionWrapper } from "@storyteller/components/src/session/SessionWrapper"; -import { GetMediaFile, MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile"; +import { + GetMediaFile, + MediaFile, +} from "@storyteller/components/src/api/media_files/GetMediaFile"; import Container from "components/common/Container"; import Panel from "components/common/Panel"; import PageHeader from "components/layout/PageHeader"; @@ -14,8 +17,8 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCircleExclamation, faArrowDownToLine, - faCirclePlay, - faShare, + // faCirclePlay, + // faShare, faSquareQuote, } from "@fortawesome/pro-solid-svg-icons"; import Accordion from "components/common/Accordion"; @@ -31,7 +34,9 @@ interface MediaPageProps { export default function MediaPage({ sessionWrapper }: MediaPageProps) { const { token } = useParams<{ token: string }>(); - const [mediaFile, setMediaFile] = useState<MediaFile | undefined | null>(null); + const [mediaFile, setMediaFile] = useState<MediaFile | undefined | null>( + null + ); const [isLoading, setIsLoading] = useState<boolean>(true); const [error, setError] = useState<boolean>(false); @@ -86,18 +91,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { if (isLoading) return ( <> - <Container type="padded"> - <div className="pt-4 pb-4"> - <h2 className="fw-bold mb-1 pt-0 pt-lg-1"> - <Skeleton type="short" /> - </h2> - <p className="mb-0"> - <Skeleton type="medium" /> - </p> - </div> - </Container> - - <Container type="padded"> + <Container type="padded" className="pt-4 pt-lg-5"> <div className="row g-4"> <div className="col-12 col-xl-8"> <div className="panel p-3 py-4 p-md-4"> @@ -193,14 +187,10 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { }, ]; - let pageTitle = "Result"; - let pageSubText = "This is the result of your media."; let mediaDetails = undefined; switch (mediaFile.media_type) { case MediaFileType.Audio: - pageTitle = "Audio Result"; - pageSubText = mediaFile.token; mediaDetails = ( <Accordion.Item title="Audio Details" defaultOpen={true}> <DataTable data={audioDetails} /> @@ -208,8 +198,6 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { ); break; case MediaFileType.Video: - pageTitle = "Video Result"; - pageSubText = mediaFile.token; mediaDetails = ( <Accordion.Item title="Video Details" defaultOpen={true}> <DataTable data={videoDetails} /> @@ -217,8 +205,6 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { ); break; case MediaFileType.Image: - pageTitle = "Image Model"; - pageSubText = "Image Model SubText"; break; default: } @@ -254,14 +240,9 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { } return ( - <> - <Container type="padded" className="py-5"> - <h2 className="fw-bold mb-1">{pageTitle}</h2> - <p className="mb-0">{pageSubText}</p> - </Container> - - <Container type="panel"> - <div className="row g-4 mb-4"> + <div> + <Container type="panel" className="pt-4 pt-lg-5"> + <div className="row g-4"> <div className="col-12 col-xl-8"> <div className="media-wrapper"> {renderMediaComponent(mediaFile)} @@ -307,7 +288,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { onClick={() => {}} className="flex-grow-1" /> - <div className="d-flex gap-2"> + {/* <div className="d-flex gap-2"> <Button square={true} variant="secondary" @@ -322,7 +303,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { onClick={() => {}} tooltip="Share" /> - </div> + </div> */} </div> <Accordion> @@ -346,6 +327,6 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </Panel> </Container> </div> - </> + </div> ); } From e057356af0677623ab8cd26ae01dce0a024a98e4 Mon Sep 17 00:00:00 2001 From: BFlat <bflat@storyteller.ai> Date: Fri, 20 Oct 2023 06:29:54 +0700 Subject: [PATCH 43/51] media audio view updates (#311) * remove header title * update * commented out buttons for now * audio player view fixes and styling updates --- .../fakeyou.com/src/scss/site-refresh.scss | 11 +++- .../v2/view/pages/media/MediaAudioPlayer.tsx | 65 +++++++++--------- .../src/v2/view/pages/media/MediaPage.tsx | 66 ++++++++++++------- .../src/v2/view/pages/premium/PricingPage.tsx | 2 +- 4 files changed, 85 insertions(+), 59 deletions(-) diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index da4780ee4c..f45ea3846a 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -310,6 +310,15 @@ styles with important tags: box-shadow: none !important; } + .video-bg { + background-color: $black; + } + + .panel-border { + border-color: #ffffff12 !important; + border: 1px solid; + } + .panel-inner { background-color: lighten($panel, 4%); } @@ -510,7 +519,7 @@ styles with important tags: box-shadow: none; } - .panel-border { + .pricing-border { box-sizing: border-box; box-shadow: inset 0px 0px 0px 3px $primary; } diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx index 4b5cd6481b..283b7dbdee 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaAudioPlayer.tsx @@ -2,9 +2,14 @@ import React from "react"; import WaveSurfer from "wavesurfer.js"; import { useEffect, useState } from "react"; import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faPlay, faPause } from "@fortawesome/pro-solid-svg-icons"; +import { + faPlay, + faPause, + faRepeat, + faArrowRight, +} from "@fortawesome/pro-solid-svg-icons"; import { MediaFile } from "@storyteller/components/src/api/media_files/GetMediaFile"; +import Button from "components/common/Button"; enum PlaybackSpeed { HALF, @@ -26,13 +31,12 @@ export default function MediaAudioPlayer({ mediaFile }: MediaAudioPlayerProps) { const wavesurferInstance = WaveSurfer.create({ container: "#waveform", // Previousy I used 'this.ref.current' and React.createRef() height: 200, - responsive: true, waveColor: "#cbcbcb", progressColor: "#fc8481", cursorColor: "#fc6b68", cursorWidth: 2, - normalize: false, + normalize: true, }); setWaveSurfer(wavesurferInstance); @@ -93,20 +97,12 @@ export default function MediaAudioPlayer({ mediaFile }: MediaAudioPlayerProps) { setPlaybackSpeed(nextSpeed); }; - let playButtonText = ( - <> - <FontAwesomeIcon icon={faPlay} /> - </> - ); + let playButtonIcon = faPlay; if (isPlaying) { - playButtonText = ( - <> - <FontAwesomeIcon icon={faPause} /> - </> - ); + playButtonIcon = faPause; } - let repeatButtonText = isRepeating ? "Repeat" : "NoRepeat"; + let repeatButtonIcon = isRepeating ? faRepeat : faArrowRight; let speedButtonText = "1x"; switch (playbackSpeed) { @@ -117,33 +113,34 @@ export default function MediaAudioPlayer({ mediaFile }: MediaAudioPlayerProps) { speedButtonText = "2x"; break; case PlaybackSpeed.HALF: - speedButtonText = "1/2x"; + speedButtonText = "0.5x"; break; } return ( <div> <div id="waveform"></div> - <div className="d-flex gap-4 flex-column justify-content-center align-items-center mt-4"> - <div className="d-flex gap-2"> - <button className="btn btn-primary" onClick={() => togglePlayPause()}> - {playButtonText} - </button> + <div className="d-flex justify-content-center gap-2 mt-3"> + <Button + square={true} + icon={playButtonIcon} + onClick={() => togglePlayPause()} + /> - <button - className="btn btn-secondary" - onClick={() => toggleIsRepeating()} - > - {repeatButtonText} - </button> + <Button + tooltip="Toggle Repeat" + variant="secondary" + square={true} + icon={repeatButtonIcon} + onClick={() => toggleIsRepeating()} + /> - <button - className="btn btn-secondary" - onClick={() => togglePlaybackSpeed()} - > - {speedButtonText} - </button> - </div> + <Button + tooltip="Speed" + label={speedButtonText} + variant="secondary" + onClick={() => togglePlaybackSpeed()} + /> </div> </div> ); diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 2ae398610a..003f710653 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -61,24 +61,39 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { switch (mediaFile.media_type) { case MediaFileType.Audio: return ( - <div className="panel p-3 p-lg-4 d-flex flex-column gap-4 rounded"> + <div className="panel p-3 p-lg-4 d-flex flex-column"> + {/* Voice model name that is used to generate the audio */} + <h3 className="fw-bold mb-4">[Voice Model Name]</h3> + <MediaAudioComponent mediaFile={mediaFile} /> - <div> - <h5 className="fw-semibold"> - <FontAwesomeIcon icon={faSquareQuote} className="me-2" /> - Audio Text - </h5> - {/*<p>{mediaFile?.audio_text && mediaFile.audio_text}</p>*/} - </div> + + {/* Show TTS text input if it is a TTS result */} + {mediaFile.public_bucket_path.includes("tts_inference_output") && ( + <div className="mt-4"> + <h5 className="fw-semibold"> + <FontAwesomeIcon icon={faSquareQuote} className="me-2" /> + Audio Text + </h5> + <p> + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed + do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Pellentesque elit ullamcorper dignissim cras tincidunt + lobortis. Integer malesuada nunc vel risus commodo viverra + maecenas accumsan lacus. + </p> + </div> + )} </div> ); case MediaFileType.Video: return ( - <div className="panel panel-clear"> - <div className="ratio ratio-16x9"> - <MediaVideoComponent mediaFile={mediaFile} /> + <> + <div className="panel panel-clear"> + <div className="ratio ratio-16x9 video-bg panel-border rounded"> + <MediaVideoComponent mediaFile={mediaFile} /> + </div> </div> - </div> + </> ); case MediaFileType.Image: @@ -187,24 +202,26 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { }, ]; + const imageDetails = [ + { property: "Type", value: mediaFile.media_type }, + { property: "Created at", value: mediaFile.created_at.toString() }, + { + property: "Visibility", + value: mediaFile.creator_set_visibility.toString(), + }, + ]; + let mediaDetails = undefined; switch (mediaFile.media_type) { case MediaFileType.Audio: - mediaDetails = ( - <Accordion.Item title="Audio Details" defaultOpen={true}> - <DataTable data={audioDetails} /> - </Accordion.Item> - ); + mediaDetails = <DataTable data={audioDetails} />; break; case MediaFileType.Video: - mediaDetails = ( - <Accordion.Item title="Video Details" defaultOpen={true}> - <DataTable data={videoDetails} /> - </Accordion.Item> - ); + mediaDetails = <DataTable data={videoDetails} />; break; case MediaFileType.Image: + mediaDetails = <DataTable data={imageDetails} />; break; default: } @@ -307,7 +324,10 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> <Accordion> - {mediaDetails} + <Accordion.Item title="Video Details" defaultOpen={true}> + {mediaDetails} + </Accordion.Item> + {modMediaDetails} </Accordion> </div> diff --git a/packages/fakeyou.com/src/v2/view/pages/premium/PricingPage.tsx b/packages/fakeyou.com/src/v2/view/pages/premium/PricingPage.tsx index 039364da46..47822836db 100644 --- a/packages/fakeyou.com/src/v2/view/pages/premium/PricingPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/premium/PricingPage.tsx @@ -143,7 +143,7 @@ function PricingPage(props: Props) { // Highlight the mid-tier plan if nothing is subscribed if (!userHasPaidPremium) { - proBorderCss = "rounded panel p-4 h-100 panel-border"; + proBorderCss = "rounded panel p-4 h-100 pricing-border"; } return ( From 27a27c1cb8d91b2200cdc9da61d64d28a57ba383 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 20 Oct 2023 07:32:33 +0700 Subject: [PATCH 44/51] button icon flip prop --- .../src/components/common/Button/Button.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/fakeyou.com/src/components/common/Button/Button.tsx b/packages/fakeyou.com/src/components/common/Button/Button.tsx index cc68fe70a7..364f2b23d0 100644 --- a/packages/fakeyou.com/src/components/common/Button/Button.tsx +++ b/packages/fakeyou.com/src/components/common/Button/Button.tsx @@ -17,6 +17,7 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { square?: boolean; tooltip?: string; full?: boolean; + iconFlip?: boolean; } export default function Button({ @@ -30,11 +31,14 @@ export default function Button({ square, tooltip, full = false, + iconFlip = false, ...rest }: ButtonProps) { + let iconMarginClass = !square && label ? (iconFlip ? "ms-2" : "me-2") : ""; let IconComponent = icon ? ( - <FontAwesomeIcon icon={icon} className={!square && label ? "me-2" : ""} /> + <FontAwesomeIcon icon={icon} className={iconMarginClass} /> ) : null; + let LabelComponent = !square ? label : null; const externalClass = rest.className || ""; @@ -47,7 +51,12 @@ export default function Button({ delete rest.className; - const ButtonContent = ( + const ButtonContent = iconFlip ? ( + <> + {LabelComponent} + {IconComponent} + </> + ) : ( <> {IconComponent} {LabelComponent} From 0d3657b8bbbf6732f27b34280e71266584c3948b Mon Sep 17 00:00:00 2001 From: Victor Holguin <olivicmic@MacBook-Pro.hitronhub.home> Date: Thu, 19 Oct 2023 22:35:51 -0700 Subject: [PATCH 45/51] face animator links to media pages --- .../public/locales/en/FaceAnimator.json | 6 ++++-- .../src/components/common/index.tsx | 2 ++ .../LipsyncEditor/FaceAnimatorJobs.tsx | 20 ++++++++----------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/fakeyou.com/public/locales/en/FaceAnimator.json b/packages/fakeyou.com/public/locales/en/FaceAnimator.json index f1bbaeacda..c47dc54e43 100644 --- a/packages/fakeyou.com/public/locales/en/FaceAnimator.json +++ b/packages/fakeyou.com/public/locales/en/FaceAnimator.json @@ -3,12 +3,14 @@ "audio": "Audio", "image": "Image", "subtitle": "Select and image with a clear face, and an audio sample, and generate a lipsynced video.", - "title": "Face Animator" + "title": "Face Animator", + "yourJobs": "Your jobs" }, "inputs": { "downloadFile": "Download File", "generate": "Generate", - "makeAnother": "Make another" + "makeAnother": "Make another", + "viewResult": "View result" }, "status": { "animationComplete": "Animation complete!", diff --git a/packages/fakeyou.com/src/components/common/index.tsx b/packages/fakeyou.com/src/components/common/index.tsx index 0401d60177..381ca1e40a 100644 --- a/packages/fakeyou.com/src/components/common/index.tsx +++ b/packages/fakeyou.com/src/components/common/index.tsx @@ -1,5 +1,6 @@ import AudioInput from "./AudioInput"; import BasicVideo from "./BasicVideo"; +import Button from "./Button"; import Check from "./Check"; import Checkbox from "./Checkbox"; import FileActions from "./FileActions"; @@ -16,6 +17,7 @@ import Spinner from "./Spinner"; export { AudioInput, BasicVideo, + Button, Check, Checkbox, FileActions, diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx index ebd68e9a55..c0ef1dc8b7 100644 --- a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx @@ -7,10 +7,10 @@ import { } from "@storyteller/components/src/api/tts/GetPendingTtsJobCount"; // import { springs } from "resources"; import { useInferenceJobs } from "hooks"; -import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; +import { Button } from 'components/common'; import { Analytics } from "common/Analytics"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faDownload, faHourglass1, faRemove, faTrophy, faWarning } from "@fortawesome/free-solid-svg-icons"; +import { faChevronRight, faHourglass1, faRemove, faTrophy, faWarning } from "@fortawesome/free-solid-svg-icons"; const DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS = 15000; @@ -22,7 +22,6 @@ export default function FaceAnimatorJobs({ t }: { t: any }) { cache_time: new Date(0), // NB: Epoch is used for vector clock's initial state refresh_interval_millis: DEFAULT_QUEUE_REFRESH_INTERVAL_MILLIS, }); - const mediaLink = (path: string) => new BucketConfig().getGcsUrl(path); const statusIcons = [faHourglass1,faHourglass1,faWarning,faRemove,faTrophy]; const statusTxt = (which: number, config = {}) => ["animationPending","animationInProgress","animationFailed","animationDead","animationSuccess"].map((str,i) => t(`status.${str}`,config))[which]; @@ -63,7 +62,7 @@ export default function FaceAnimatorJobs({ t }: { t: any }) { }, [pending]); return inferenceJobs.length ? <div {...{ className: "face-animator-jobs panel" }}> - <h5>Your jobs</h5> + <h5>{ t("headings.yourJobs") }</h5> { inferenceJobs.map((job, key) => { return <div {...{ className: "panel face-animator-job", key }}> <FontAwesomeIcon {...{ className: `job-status-icon job-status-${job.statusIndex}`, icon: statusIcons[job.statusIndex] }}/> @@ -75,15 +74,12 @@ export default function FaceAnimatorJobs({ t }: { t: any }) { <span {...{ className: "job-id" }}>id: { job.jobToken }</span> </div> { - job.maybeResultToken ? <a {...{ - className: "btn btn-primary", - download: `fakeyou-${job.jobToken}.mp4`, - href: mediaLink(job.maybeResultPublicBucketMediaPath || ""), + job.maybeResultToken ? <Button {...{ + href: `media/${job.maybeResultToken}`, + icon: faChevronRight, + label: t("inputs.viewResult"), onClick:() => Analytics.voiceConversionClickDownload() - }}> - <FontAwesomeIcon icon={faDownload} className="me-2" /> - { t("inputs.downloadFile") } - </a> : null + }} />: null } </div> }).reverse()} From 9b186056b93c830c58ad7092b3514106d9e97f5c Mon Sep 17 00:00:00 2001 From: Victor Holguin <olivicmic@MacBook-Pro.hitronhub.home> Date: Thu, 19 Oct 2023 23:34:26 -0700 Subject: [PATCH 46/51] face animator result button icon flip --- .../src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx index c0ef1dc8b7..3ce3b3425e 100644 --- a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx @@ -77,6 +77,7 @@ export default function FaceAnimatorJobs({ t }: { t: any }) { job.maybeResultToken ? <Button {...{ href: `media/${job.maybeResultToken}`, icon: faChevronRight, + iconFlip: true, label: t("inputs.viewResult"), onClick:() => Analytics.voiceConversionClickDownload() }} />: null From f9907aa81ca6005a805eedaeab70a38dec4e0756 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 20 Oct 2023 16:30:31 +0700 Subject: [PATCH 47/51] media page button download attribute --- .../src/components/common/Button/Button.tsx | 12 +++++++++++- .../src/v2/view/pages/media/MediaPage.tsx | 6 +++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/fakeyou.com/src/components/common/Button/Button.tsx b/packages/fakeyou.com/src/components/common/Button/Button.tsx index 364f2b23d0..2aaafcd5b3 100644 --- a/packages/fakeyou.com/src/components/common/Button/Button.tsx +++ b/packages/fakeyou.com/src/components/common/Button/Button.tsx @@ -18,6 +18,7 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> { tooltip?: string; full?: boolean; iconFlip?: boolean; + download?: boolean | string; } export default function Button({ @@ -32,6 +33,7 @@ export default function Button({ tooltip, full = false, iconFlip = false, + download, ...rest }: ButtonProps) { let iconMarginClass = !square && label ? (iconFlip ? "ms-2" : "me-2") : ""; @@ -68,7 +70,15 @@ export default function Button({ {ButtonContent} </Link> ) : href ? ( - <a href={href} target={target} rel="noopener noreferrer" {...commonProps}> + <a + href={href} + target={target} + rel="noopener noreferrer" + download={ + download ? (typeof download === "string" ? download : true) : undefined + } + {...commonProps} + > {ButtonContent} </a> ) : ( diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 003f710653..9f8093c378 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -27,6 +27,7 @@ import { Gravatar } from "@storyteller/components/src/elements/Gravatar"; import useTimeAgo from "hooks/useTimeAgo"; import { CommentComponent } from "v2/view/_common/comments/CommentComponent"; import { MediaFileType } from "@storyteller/components/src/api/_common/enums/MediaFileType"; +import { BucketConfig } from "@storyteller/components/src/api/BucketConfig"; interface MediaPageProps { sessionWrapper: SessionWrapper; @@ -103,6 +104,8 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { } } + let audioLink = new BucketConfig().getGcsUrl(mediaFile?.public_bucket_path); + if (isLoading) return ( <> @@ -302,8 +305,9 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { <Button icon={faArrowDownToLine} label="Download" - onClick={() => {}} className="flex-grow-1" + href={audioLink} + download={true} /> {/* <div className="d-flex gap-2"> <Button From 25539b14e4f09de5de48e4725384a81a79108602 Mon Sep 17 00:00:00 2001 From: Brandon Thomas <echelon@gmail.com> Date: Fri, 20 Oct 2023 06:01:52 -0400 Subject: [PATCH 48/51] link to the media page --- .../SessionVoiceConversionResultsList.tsx | 26 +++---------- .../src/v2/view/pages/media/MediaPage.tsx | 37 +++++++------------ 2 files changed, 20 insertions(+), 43 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/_common/SessionVoiceConversionResultsList.tsx b/packages/fakeyou.com/src/v2/view/_common/SessionVoiceConversionResultsList.tsx index 6d5103c7e2..c52fa5e16e 100644 --- a/packages/fakeyou.com/src/v2/view/_common/SessionVoiceConversionResultsList.tsx +++ b/packages/fakeyou.com/src/v2/view/_common/SessionVoiceConversionResultsList.tsx @@ -6,7 +6,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faClock, faHeadphonesSimple, - faDownload, + faLink, } from "@fortawesome/free-solid-svg-icons"; import { SessionSubscriptionsWrapper } from "@storyteller/components/src/session/SessionSubscriptionsWrapper"; @@ -120,12 +120,10 @@ function SessionVoiceConversionResultsList(props: Props) { let audioLink = new BucketConfig().getGcsUrl( job.maybeResultPublicBucketMediaPath ); - //let ttsPermalink = `/tts/result/${job.maybeResultToken}`; + let audioPermalink = `/media/${job.maybeResultToken}`; let wavesurfers = <SessionTtsAudioPlayer filename={audioLink} />; - let audioDownloadFilename = `fakeyou-${job.jobToken}.wav`; - results.push( <div key={job.jobToken}> {/*<div className="message-header"> @@ -154,28 +152,16 @@ function SessionVoiceConversionResultsList(props: Props) { {wavesurfers} <div className="mt-2"> - {/*<Link - to={ttsPermalink} + <Link + to={audioPermalink} onClick={() => { - Analytics.ttsClickResultLink(); + //Analytics.ttsClickResultLink(); }} className="fw-semibold" > <FontAwesomeIcon icon={faLink} className="me-2" /> - {t("common.SessionTtsInferenceResults.result.shareDownload")} - </Link>*/} - - <a - className=" btn btn-primary w-100 mt-4" - href={audioLink} - onClick={() => { - Analytics.voiceConversionClickDownload(); - }} - download={audioDownloadFilename} - > - <FontAwesomeIcon icon={faDownload} className="me-2" /> {t("resultsAudioDownload")} - </a> + </Link> </div> </div> </div> diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 9f8093c378..cc1abf8811 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -64,7 +64,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { return ( <div className="panel p-3 p-lg-4 d-flex flex-column"> {/* Voice model name that is used to generate the audio */} - <h3 className="fw-bold mb-4">[Voice Model Name]</h3> + {/*<h3 className="fw-bold mb-4">[Voice Model Name]</h3> */} <MediaAudioComponent mediaFile={mediaFile} /> @@ -302,29 +302,20 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> <div className="d-flex gap-2 flex-wrap"> - <Button - icon={faArrowDownToLine} - label="Download" - className="flex-grow-1" + + <a href={audioLink} - download={true} - /> - {/* <div className="d-flex gap-2"> - <Button - square={true} - variant="secondary" - icon={faCirclePlay} - onClick={() => {}} - tooltip="Create" - /> - <Button - square={true} - variant="secondary" - icon={faShare} - onClick={() => {}} - tooltip="Share" - /> - </div> */} + download={audioLink} + onClick={() => { + //Analytics.ttsClickResultLink(); + }} + className=" btn btn-primary w-100 mt-4" + + > + <FontAwesomeIcon icon={faArrowDownToLine} className="me-2" /> + Download + </a> + </div> <Accordion> From 501b996666d7e27687cb253539c02491ba4cac99 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Fri, 20 Oct 2023 20:33:25 +0700 Subject: [PATCH 49/51] button component download --- .../src/v2/view/pages/media/MediaPage.tsx | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index cc1abf8811..3b1e15b9c8 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -302,20 +302,30 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> <div className="d-flex gap-2 flex-wrap"> - - <a + <Button + icon={faArrowDownToLine} + label="Download" + className="flex-grow-1" href={audioLink} download={audioLink} - onClick={() => { - //Analytics.ttsClickResultLink(); - }} - className=" btn btn-primary w-100 mt-4" - - > - <FontAwesomeIcon icon={faArrowDownToLine} className="me-2" /> - Download - </a> - + /> + {/* Share and Create Buttons */} + {/* <div className="d-flex gap-2"> + <Button + square={true} + variant="secondary" + icon={faCirclePlay} + onClick={() => {}} + tooltip="Create" + /> + <Button + square={true} + variant="secondary" + icon={faShare} + onClick={() => {}} + tooltip="Share" + /> + </div> */} </div> <Accordion> From c9c10072943db78c8b687030b10ada4827fd9992 Mon Sep 17 00:00:00 2001 From: BFlat <bombayapirat@gmail.com> Date: Tue, 24 Oct 2023 03:17:43 +0700 Subject: [PATCH 50/51] media details text --- packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx index 3b1e15b9c8..8b1cef17a0 100644 --- a/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/media/MediaPage.tsx @@ -329,7 +329,7 @@ export default function MediaPage({ sessionWrapper }: MediaPageProps) { </div> <Accordion> - <Accordion.Item title="Video Details" defaultOpen={true}> + <Accordion.Item title="Media Details" defaultOpen={true}> {mediaDetails} </Accordion.Item> From 720e9d66fcba2e9290855cd610b5fee0bd5fccbe Mon Sep 17 00:00:00 2001 From: Victor Holguin <olivicmic@Tin-Man.hitronhub.home> Date: Tue, 24 Oct 2023 22:03:07 -0700 Subject: [PATCH 51/51] added failure states to face animator --- .../GetModelInferenceJobStatus.ts | 1 + packages/components/src/jobs/InferenceJob.ts | 7 +++++++ .../components/common/Checkbox/Checkbox.tsx | 2 +- .../common/SegmentButtons/SegmentButtons.tsx | 3 ++- .../LipsyncEditor/FaceAnimatorJobs.tsx | 21 ++++++++++--------- .../lipsync/LipsyncEditor/LipsyncEditor.scss | 15 +++++++++---- 6 files changed, 33 insertions(+), 16 deletions(-) diff --git a/packages/components/src/api/model_inference/GetModelInferenceJobStatus.ts b/packages/components/src/api/model_inference/GetModelInferenceJobStatus.ts index 2da780cdef..3610bcf052 100644 --- a/packages/components/src/api/model_inference/GetModelInferenceJobStatus.ts +++ b/packages/components/src/api/model_inference/GetModelInferenceJobStatus.ts @@ -30,6 +30,7 @@ export interface RequestDetails { export interface StatusDetails { status: string, maybe_extra_status_description?: string, + maybe_failure_category?: string, attempt_count: number, } diff --git a/packages/components/src/jobs/InferenceJob.ts b/packages/components/src/jobs/InferenceJob.ts index 586126aa83..638530ee56 100644 --- a/packages/components/src/jobs/InferenceJob.ts +++ b/packages/components/src/jobs/InferenceJob.ts @@ -31,6 +31,7 @@ export class InferenceJob { maybeResultType: string | undefined | null; maybeResultToken: string | undefined | null; maybeResultPublicBucketMediaPath: string | undefined | null; + maybeFailureCategory: string | undefined | null; constructor( // PK @@ -50,6 +51,7 @@ export class InferenceJob { maybeResultEntityType: string | undefined | null = null, maybeResultEntityToken: string | undefined | null = null, maybeResultPublicBucketMediaPath: string | undefined | null = null, + maybeFailureCategory: string | undefined | null = null ) { this.jobToken = jobToken; this.frontendJobType = frontendJobType; @@ -77,6 +79,10 @@ export class InferenceJob { } this.maybeResultPublicBucketMediaPath = maybeResultPublicBucketMediaPath; + + if (!!maybeFailureCategory) { + this.maybeFailureCategory = maybeFailureCategory; + } } static fromResponse(response: ModelInferenceJobStatus, frontendJobType: FrontendInferenceJobType) : InferenceJob { @@ -93,6 +99,7 @@ export class InferenceJob { response.maybe_result?.entity_type, response.maybe_result?.entity_token, response.maybe_result?.maybe_public_bucket_media_path, + response.status.maybe_failure_category ); } } diff --git a/packages/fakeyou.com/src/components/common/Checkbox/Checkbox.tsx b/packages/fakeyou.com/src/components/common/Checkbox/Checkbox.tsx index 35826acf2a..8f3d0b2176 100644 --- a/packages/fakeyou.com/src/components/common/Checkbox/Checkbox.tsx +++ b/packages/fakeyou.com/src/components/common/Checkbox/Checkbox.tsx @@ -25,6 +25,6 @@ export default function Checkbox({ checked, className = "", label = "", name = " <a.svg {...{ className: "fy-checkbox", onClick, style, ...hoverEvents }}> <Check {...{ checked }}/> </a.svg> - { label && <label {...{ className: "form-check-label", for: id, onClick }}>{ label }</label> } + { label && <label {...{ className: "form-check-label", htmlFor: id, onClick }}>{ label }</label> } </div> }; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/SegmentButtons/SegmentButtons.tsx b/packages/fakeyou.com/src/components/common/SegmentButtons/SegmentButtons.tsx index d13c2384a6..9f9e66d4ff 100644 --- a/packages/fakeyou.com/src/components/common/SegmentButtons/SegmentButtons.tsx +++ b/packages/fakeyou.com/src/components/common/SegmentButtons/SegmentButtons.tsx @@ -11,8 +11,9 @@ interface Props { export default function SegmentButtons({ name, onChange, options = [], value: inValue = "" }: Props) { // const onClick = ({ target }: any) => onChange(); return <ul {...{ className: "fy-segment-buttons" }}> - { options.map(({ label = "", value = "" },i: number) => <li {...{ + { options.map(({ label = "", value = "" },key: number) => <li {...{ ...value === inValue && { className: "fy-selected-segment" }, + key, onClick: ({ target }: any) => onChange({ target: { name, type: "option", value } }) }}>{ label }</li>) } </ul>; diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx index 3ce3b3425e..6692b07198 100644 --- a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/FaceAnimatorJobs.tsx @@ -25,12 +25,12 @@ export default function FaceAnimatorJobs({ t }: { t: any }) { const statusIcons = [faHourglass1,faHourglass1,faWarning,faRemove,faTrophy]; const statusTxt = (which: number, config = {}) => ["animationPending","animationInProgress","animationFailed","animationDead","animationSuccess"].map((str,i) => t(`status.${str}`,config))[which]; - // const processFail = (fail = "") => { - // switch (fail) { - // case "face_not_detected": return "Face not detected, try another picture"; - // default: return "Uknown failure"; - // } - // }; + const processFail = (fail = "") => { + switch (fail) { + case "face_not_detected": return "Face not detected, try another picture"; + default: return "Uknown failure"; + } + }; // const transitions = useTransition(inferenceJobs, { // not today // ...springs.soft, @@ -67,11 +67,12 @@ export default function FaceAnimatorJobs({ t }: { t: any }) { return <div {...{ className: "panel face-animator-job", key }}> <FontAwesomeIcon {...{ className: `job-status-icon job-status-${job.statusIndex}`, icon: statusIcons[job.statusIndex] }}/> <div {...{ className: "job-details" }}> - <h6> + <h4> { statusTxt(job.statusIndex,{ attemptCount: job.attemptCount || "" }) } - {/*{ job.maybeFailureCategory ? `: ${ processFail(job.maybeFailureCategory) }` : "" }*/} - </h6> - <span {...{ className: "job-id" }}>id: { job.jobToken }</span> + </h4> + <span> + { job.maybeFailureCategory ? `${ processFail(job.maybeFailureCategory) }` : "" } + </span> </div> { job.maybeResultToken ? <Button {...{ diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.scss b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.scss index 5de506eb8a..bea99a1c9b 100644 --- a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.scss +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.scss @@ -171,6 +171,7 @@ $over992: min-width 992px; .face-animator-job { display: flex; flex-wrap: wrap; + align-items: stretch; margin-top: 1rem; padding: 1rem; @@ -194,12 +195,18 @@ $over992: min-width 992px; .job-status-4 { background-color: $success } // success = green .job-details { - // display: flex; + display: flex; align-items: center; - height: 100%; - // width: 100%; + flex-wrap: wrap; + // height: 100%; + width: min-content; + + h4, span { white-space: nowrap; } - h6 { line-height: 1em } + h4 { + line-height: 1em; + margin-bottom: 0; + } }