diff --git a/packages/fakeyou.com/src/components/common/AudioInput/AudioInput.scss b/packages/fakeyou.com/src/components/common/AudioInput/AudioInput.scss new file mode 100644 index 0000000000..73d95b4aad --- /dev/null +++ b/packages/fakeyou.com/src/components/common/AudioInput/AudioInput.scss @@ -0,0 +1 @@ +.fy-audio-uploader > div { margin-bottom: 1rem } \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/AudioInput/AudioInput.tsx b/packages/fakeyou.com/src/components/common/AudioInput/AudioInput.tsx new file mode 100644 index 0000000000..7e90e4312b --- /dev/null +++ b/packages/fakeyou.com/src/components/common/AudioInput/AudioInput.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import { InputVcAudioPlayer } from "v2/view/_common/InputVcAudioPlayer"; +import { FileActions, FileDetails, FileLabel, FileWrapper } from 'components/common'; +import { faFileAudio } from "@fortawesome/pro-solid-svg-icons"; +import './AudioInput.scss' + +const fileTypes = ["MP3", "WAV", "FLAC", "OGG"]; + +interface Props { + blob?: string; + clear?: (file?: any) => void; + file?: any; + hideActions?: boolean; + hideClearDetails?: boolean; + inputProps?: any; + success?: boolean; + submit?: () => void; + working?: boolean; + [x:string]: any; +} + +const n = () => {}; + +export default function AudioInput({ blob = "", clear = n, file, hideActions, hideClearDetails, inputProps, success = false, submit = n, working = false, ...rest }: Props) { + + return
+ + { file ? : } + + { file && <> +
+ +
+ { !hideActions && } + } +
; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/AudioInput/index.tsx b/packages/fakeyou.com/src/components/common/AudioInput/index.tsx new file mode 100644 index 0000000000..919bf06fd5 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/AudioInput/index.tsx @@ -0,0 +1 @@ +export { default } from './AudioInput'; diff --git a/packages/fakeyou.com/src/components/common/FileActions/FileActions.tsx b/packages/fakeyou.com/src/components/common/FileActions/FileActions.tsx new file mode 100644 index 0000000000..d7062684b8 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileActions/FileActions.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { FontAwesomeIcon as Icon } from "@fortawesome/react-fontawesome"; +import { faCheck, faFileArrowUp, faTrash } from "@fortawesome/pro-solid-svg-icons"; +import LoadingIcon from "./LoadingIcon"; + +interface Props { + clear?: (x?: any) => void; + upload?: (x?: any) => void; + successful?: boolean; + working?: boolean; +} + +const n = () => {}; + +export default function FileActions({ clear = n, upload = n, successful, working }: Props) { + const uploadBtnClass = successful ? "btn btn-uploaded w-100 disabled" : "btn btn-primary w-100"; + + return
+ + +
; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/FileActions/LoadingIcon.tsx b/packages/fakeyou.com/src/components/common/FileActions/LoadingIcon.tsx new file mode 100644 index 0000000000..dce6894198 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileActions/LoadingIcon.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +export default function LoadingIcon() { + return <> + + Loading... + ; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/FileActions/index.tsx b/packages/fakeyou.com/src/components/common/FileActions/index.tsx new file mode 100644 index 0000000000..02ee6bf0e4 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileActions/index.tsx @@ -0,0 +1 @@ +export { default } from './FileActions'; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/FileDetails/FileDetails.scss b/packages/fakeyou.com/src/components/common/FileDetails/FileDetails.scss new file mode 100644 index 0000000000..1f5d412f66 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileDetails/FileDetails.scss @@ -0,0 +1,10 @@ +.upload-details { + width: 100%; + + .upload-details-clear { + height: 36px; + width: 36px; + margin: auto 0 auto auto; + padding: 10px; + } +} \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/FileDetails/FileDetails.tsx b/packages/fakeyou.com/src/components/common/FileDetails/FileDetails.tsx new file mode 100644 index 0000000000..0c4250af52 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileDetails/FileDetails.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { FontAwesomeIcon as Icon } from "@fortawesome/react-fontawesome"; +import { faTrash } from "@fortawesome/pro-solid-svg-icons"; +import "./FileDetails.scss"; + +interface Props { + clear?: (file?: any) => void; + file?: any; + hideClearDetails?: boolean; + icon?: any; +} + +export default function FileDetails({ clear = () => {}, file, hideClearDetails, icon }: Props) { + const fileSize = + file && file.size >= 1024 * 1024 + ? (file.size / 1024 / 1024).toFixed(2) + " MB" + : file + ? `${Math.floor(file.size / 1024)} KB` + : null; + + return
+ +
+
+ { file.name.slice(0, file.name.lastIndexOf(".")) } +
+ + {`${ file.name.split(".").pop().toUpperCase() } file size: ${ fileSize }`} + + Change file +
+ { !hideClearDetails && } +
; +}; diff --git a/packages/fakeyou.com/src/components/common/FileDetails/index.tsx b/packages/fakeyou.com/src/components/common/FileDetails/index.tsx new file mode 100644 index 0000000000..d24335d24b --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileDetails/index.tsx @@ -0,0 +1 @@ +export { default } from './FileDetails'; diff --git a/packages/fakeyou.com/src/components/common/FileLabel/FileLabel.scss b/packages/fakeyou.com/src/components/common/FileLabel/FileLabel.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/fakeyou.com/src/components/common/FileLabel/FileLabel.tsx b/packages/fakeyou.com/src/components/common/FileLabel/FileLabel.tsx new file mode 100644 index 0000000000..6f422e8746 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileLabel/FileLabel.tsx @@ -0,0 +1,20 @@ +import React from "react"; +import { FontAwesomeIcon as Icon } from "@fortawesome/react-fontawesome"; +import { faFileArrowUp } from "@fortawesome/pro-solid-svg-icons"; +import "./FileLabel.scss"; + +interface Props { + fileTypes?: string[]; +} + +export default function FileLabel({ fileTypes = [] }: Props) { + return
+ +
+ Upload a file or drop it here... +

+ { fileTypes.join(", ").toString() } supported +

+
+
; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/FileLabel/index.tsx b/packages/fakeyou.com/src/components/common/FileLabel/index.tsx new file mode 100644 index 0000000000..28efdc8e72 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileLabel/index.tsx @@ -0,0 +1 @@ +export { default } from './FileLabel'; diff --git a/packages/fakeyou.com/src/components/common/FileWrapper/FileWrapper.scss b/packages/fakeyou.com/src/components/common/FileWrapper/FileWrapper.scss new file mode 100644 index 0000000000..8d9e467507 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileWrapper/FileWrapper.scss @@ -0,0 +1,33 @@ +@import "scss/colours.scss"; + +.fy-uploader { + [type="file"] { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + overflow: hidden; + padding: 0; + position: absolute !important; + white-space: nowrap; + width: 1px; + + + label { + cursor: pointer; + border: dashed 2px rgba(255, 255, 255, 0.12) !important; + border-radius: 0.5rem; + transition: 0.1s all; + &:hover { + background-color: lighten($panel, 6%); + } + } + } + .fy-uploader-layout { + display: flex; + align-items: center; + + .fy-uploader-layout-icon { + font-size: 2.625rem; + margin-right: 1rem; + } + } +} diff --git a/packages/fakeyou.com/src/components/common/FileWrapper/FileWrapper.tsx b/packages/fakeyou.com/src/components/common/FileWrapper/FileWrapper.tsx new file mode 100644 index 0000000000..649c6f2c81 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileWrapper/FileWrapper.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import { useId } from 'hooks'; // replace with react v18 +import './FileWrapper.scss' + +interface Props { + children?: JSX.Element|JSX.Element[]; + containerClass?: string; + fileTypes?: string[]; + inputRef: any; + onChange: (file?: any) => void; + panelClass?: string; + [x:string]: any; +}; + +export default function FileWrapper({ children, containerClass, fileTypes = [], inputRef, onChange, panelClass, ...rest }: Props) { + const id = 'file-input-' + useId(); + const accept = fileTypes.map((type,i) => `.${ type.toLowerCase() }`).join(","); + + const fileChange = (e: any) => { + e.preventDefault(); + onChange({ target: { name: e.target?.name || "file-input", value: e.target.files[0] }}); + }; + const onDragDrop = (e: any) => { e.preventDefault(); e.stopPropagation(); }; + const onDragEvent = (onOff: number) => (e: React.DragEvent): void => { + onDragDrop(e); + e.currentTarget.classList[onOff ? "add" : "remove" ]("upload-zone-drag"); + }; + const onDrop = (e: any): void => { + onDragDrop(e); + if (e.dataTransfer.files && e.dataTransfer.files[0]) { + onChange({ target: { name: e.target?.name || "file-input", value: e.dataTransfer.files[0] }}); + } + }; + + return
+ + +
; +}; diff --git a/packages/fakeyou.com/src/components/common/FileWrapper/LoadingIcon.tsx b/packages/fakeyou.com/src/components/common/FileWrapper/LoadingIcon.tsx new file mode 100644 index 0000000000..dce6894198 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileWrapper/LoadingIcon.tsx @@ -0,0 +1,12 @@ +import React from "react"; + +export default function LoadingIcon() { + return <> + + Loading... + ; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/FileWrapper/index.tsx b/packages/fakeyou.com/src/components/common/FileWrapper/index.tsx new file mode 100644 index 0000000000..56d7376ab7 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/FileWrapper/index.tsx @@ -0,0 +1 @@ +export { default } from './FileWrapper'; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/ImageInput/ImageInput.scss b/packages/fakeyou.com/src/components/common/ImageInput/ImageInput.scss new file mode 100644 index 0000000000..1ed9219673 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ImageInput/ImageInput.scss @@ -0,0 +1,39 @@ +@import "scss/colours.scss"; + +.fy-image-uploader { + display: flex; + justify-content: center; + align-items: center; + overflow: hidden; + height: 100%; + width: 100%; + + .file-preview { + height: 100%; + width: 100%; + border-radius: .5rem; + object-fit: cover; + } + .image-upload-label, .upload-details { + background-color: rgba($panel, .85); + position: absolute; + } + .image-upload-label { + border-radius: .5rem .5rem 0 0; + display: flex; + width: 100%; + top: 0; + padding: 1rem; + } + + .upload-details { + top: 1rem; + left: 1rem; + width: calc(100% - 2rem); + } + + .image-placeholder { + // background-color: red; + fill: $secondary; + } +} \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/ImageInput/ImageInput.tsx b/packages/fakeyou.com/src/components/common/ImageInput/ImageInput.tsx new file mode 100644 index 0000000000..da03a47a36 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ImageInput/ImageInput.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { FileDetails, FileWrapper, FileLabel } from "components/common"; +import "./ImageInput.scss"; + +const fileTypes = ["JPG", "GIF", "PNG"]; + +interface Props { + blob?: string; + clear?: (file?: any) => void; + file?: any; + hideActions?: boolean; + hideClearDetails?: boolean; + inputProps?: any; + success?: boolean; + submit?: () => void; + working?: boolean; + [x:string]: any; +} + +const n = () => {}; + +export default function ImageInput({ blob = "", clear = n, file, hideActions, hideClearDetails, inputProps, success = false, submit = n, working = false, ...rest }: Props) { + return +
+ { file ? <> + + + : <> + + + +
+ { !file && } +
+ } +
+
; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/common/ImageInput/index.tsx b/packages/fakeyou.com/src/components/common/ImageInput/index.tsx new file mode 100644 index 0000000000..4bcb609d53 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/ImageInput/index.tsx @@ -0,0 +1 @@ +export { default } from './ImageInput'; diff --git a/packages/fakeyou.com/src/components/common/index.tsx b/packages/fakeyou.com/src/components/common/index.tsx new file mode 100644 index 0000000000..5e570e82e2 --- /dev/null +++ b/packages/fakeyou.com/src/components/common/index.tsx @@ -0,0 +1,15 @@ +import AudioInput from './AudioInput'; +import ImageInput from './ImageInput'; +import FileActions from './FileActions'; +import FileDetails from './FileDetails'; +import FileWrapper from './FileWrapper'; +import FileLabel from './FileLabel'; + +export { + AudioInput, + ImageInput, + FileActions, + FileDetails, + FileWrapper, + FileLabel +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx new file mode 100644 index 0000000000..e0c8b6e0e4 --- /dev/null +++ b/packages/fakeyou.com/src/components/layout/PageHeader/PageHeader.tsx @@ -0,0 +1,33 @@ +import React from "react"; + +interface Props { + childProps?: any; + titleIcon?: JSX.Element; + titleComponent?: React.ComponentType; + title?: string; + subText: string; + showButtons: boolean; + 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> + )} + </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 new file mode 100644 index 0000000000..58edd62eef --- /dev/null +++ b/packages/fakeyou.com/src/components/layout/PageHeader/index.js @@ -0,0 +1 @@ +export { default } from './PageHeader'; \ No newline at end of file diff --git a/packages/fakeyou.com/src/components/layout/index.tsx b/packages/fakeyou.com/src/components/layout/index.tsx new file mode 100644 index 0000000000..110b9fc1d6 --- /dev/null +++ b/packages/fakeyou.com/src/components/layout/index.tsx @@ -0,0 +1,5 @@ +import PageHeader from './PageHeader'; + +export { + PageHeader, +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/hooks/index.tsx b/packages/fakeyou.com/src/hooks/index.tsx new file mode 100644 index 0000000000..bf9bef4f63 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/index.tsx @@ -0,0 +1,5 @@ +import useFile from './useFile'; +import useId from './useId'; +import useIdempotency from './useIdempotency'; + +export { useFile, useId, useIdempotency }; \ No newline at end of file diff --git a/packages/fakeyou.com/src/hooks/useFile/index.tsx b/packages/fakeyou.com/src/hooks/useFile/index.tsx new file mode 100644 index 0000000000..e10364a878 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useFile/index.tsx @@ -0,0 +1 @@ +export { default } from "./useFile"; \ No newline at end of file diff --git a/packages/fakeyou.com/src/hooks/useFile/useFile.tsx b/packages/fakeyou.com/src/hooks/useFile/useFile.tsx new file mode 100644 index 0000000000..f75d512939 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useFile/useFile.tsx @@ -0,0 +1,53 @@ +import { useRef, useState } from 'react'; + +const n = (o: any) => o; + +interface Props { + debug?: any; + onChange?: (file: any) => void; + onClear?: (x?: any) => void; + onSubmit?: (file: any) => boolean; +} + +export default function useFile({ debug, onChange = n, onClear = n, onSubmit = n }: Props) { + const [file, fileSet] = useState<any>(undefined); + const [blob, blobSet] = useState<string>(); + const [working, workingSet] = useState(false); + const [success, successSet] = useState<boolean>(false); + const inputRef = useRef<HTMLInputElement>(null); + + const submit = async () => { + if (file === undefined) { return false; } + const onUploadResult = await onSubmit(file); + workingSet(true); + if (onUploadResult) { successSet(true); } + successSet(false); + }; + const fileChange = (inputFile?: any) => { + onChange(file); + fileSet(inputFile || null); + blobSet(inputFile ? URL.createObjectURL(inputFile) : ""); + successSet(false); + }; + const inputChange = ({ target = {} }: { target: any }) => { + fileChange(target.value); + }; + const clear = () => { + if (inputRef?.current?.value) inputRef.current.value = ''; + fileChange(); + onClear(); + }; + + return { + blob, + clear, + file, + inputProps: { + onChange: inputChange, + inputRef + }, + submit, + success, + working, + }; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/hooks/useId/index.tsx b/packages/fakeyou.com/src/hooks/useId/index.tsx new file mode 100644 index 0000000000..bf8a1630ed --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useId/index.tsx @@ -0,0 +1 @@ +export { default } from './useId'; diff --git a/packages/fakeyou.com/src/hooks/useId/useId.tsx b/packages/fakeyou.com/src/hooks/useId/useId.tsx new file mode 100644 index 0000000000..57852ce56f --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useId/useId.tsx @@ -0,0 +1,15 @@ +import { useEffect, useState } from 'react'; + +const S4 = () => (((1+Math.random())*0x10000)|0).toString(16).substring(1); + +export default function useId() { + const [id,idSet] = useState<string>(); + + useEffect(() => { + if (!id) idSet(S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4()); + },[id]); + + return id; +}; + +// based on https://stackoverflow.com/questions/6860853/generate-random-string-for-div-id/6860916#6860916 \ No newline at end of file diff --git a/packages/fakeyou.com/src/hooks/useIdempotency/index.tsx b/packages/fakeyou.com/src/hooks/useIdempotency/index.tsx new file mode 100644 index 0000000000..fe06c4c25a --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useIdempotency/index.tsx @@ -0,0 +1 @@ +export { default } from './useIdempotency'; diff --git a/packages/fakeyou.com/src/hooks/useIdempotency/useIdempotency.tsx b/packages/fakeyou.com/src/hooks/useIdempotency/useIdempotency.tsx new file mode 100644 index 0000000000..0f264b57a0 --- /dev/null +++ b/packages/fakeyou.com/src/hooks/useIdempotency/useIdempotency.tsx @@ -0,0 +1,7 @@ +import { useState } from 'react'; +import { v4 as uuidv4 } from "uuid"; + +export default function useIdempotency() { + const [token, set] = useState(uuidv4()); + return { reset: () => set(uuidv4()), set, token }; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/v2/view/PageContainer.tsx b/packages/fakeyou.com/src/v2/view/PageContainer.tsx index 5210ac206b..10dc7ec360 100644 --- a/packages/fakeyou.com/src/v2/view/PageContainer.tsx +++ b/packages/fakeyou.com/src/v2/view/PageContainer.tsx @@ -6,6 +6,7 @@ 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 { LipsyncEditor } from "./pages/lipsync"; import { FooterNav } from "./nav/FooterNav"; import { TopNav } from "./nav/TopNav"; import { ProfileEditFc } from "./pages/profile/profile_edit/ProfileEditFc"; @@ -429,6 +430,10 @@ class PageContainer extends React.Component<Props, State> { <CreateCategoryPage sessionWrapper={this.props.sessionWrapper} /> </Route> + <Route path="/dev-lipsync"> + <LipsyncEditor /> + </Route> + <Route path="/moderation/user/list"> <ModerationUserListFc sessionWrapper={this.props.sessionWrapper} 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 new file mode 100644 index 0000000000..dc0825c225 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.scss @@ -0,0 +1,88 @@ +.lipsync-editor { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + grid-gap: 1rem; + + .grid-heading, .grid-square { + &:nth-child(odd) { + padding-left: 1rem; + } + &:nth-child(even) { + padding-right: 1rem; + } + } + + .grid-heading { + display: flex; + align-items: center; + // background-color: blue; + // padding-left: 1rem; + h5 { + margin: 1rem 0 0; + // background: red; + line-height: 1em; + } + } + + .grid-square { + aspect-ratio: 1; + padding-bottom: 1rem; + // &:nth-child(odd) { + // padding-left: 1rem; + // } + // &:nth-child(even) { + // padding-right: 1rem; + // } + } + + + + + // div.grid-square { aspect-ratio: 1 } + .fy-image-uploader { height: 100%; } + .lipsync-audio { + label { height: 100% } + } +} + +.progress-header { + display: flex; + align-items: center; + margin-bottom: 1rem; + + .progress-heading { + display: inline-block; + margin: auto 1rem auto 0; + } + + .async-progress-tracker { + display: inline-flex; + justify-content: space-around; + flex-grow: 1; + margin-right: 1rem; + padding-left: 0; + + li { + display: flex; + align-items: center; + font-size: 1.25rem; + font-weight: 500; + } + + svg { + border: 2px solid #fff; + border-radius: 50%; + margin-right: .5rem; + height: 2rem; + width: 2rem; + stroke: white; + } + } + + button { + margin: 0 0 0 auto; + background-color: #ccccff; + // flex-grow: 1; + width: fit-content; + } +} \ No newline at end of file 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 new file mode 100644 index 0000000000..17e71c5862 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/LipsyncEditor.tsx @@ -0,0 +1,76 @@ +import React from "react"; +import { useFile } from "hooks"; +import { AudioInput, ImageInput } from "components/common"; +import { PageHeader } from "components/layout"; +import './LipsyncEditor.scss'; + +// interface Props { +// audioFile?: any; +// imageFile?: any; +// } + +const ProgressCheck = ({ disabled = false }: {disabled?: boolean}) => <svg> + { !disabled && <polyline {...{ + fill: 'none', + points: '7 16 12 20 20 10', + strokeLinecap: 'round', + strokeLinejoin: 'round', + strokeWidth: '4', + }}/> } +</svg>; + +const Title = ({ ...rest }) => { + const { audioFile, imageFile } = rest; + + return <div {...{ className: 'progress-header' }}> + <h1 {...{ className: "fw-bold text-center text-md-start progress-heading" }}> + Generate a lipsync + </h1> + <ul {...{ className: 'async-progress-tracker' }}> + <li> + <ProgressCheck {...{ disabled: imageFile }}/> + Image + </li> + <li> + <ProgressCheck {...{ disabled: audioFile }}/> + Audio + </li> + </ul> + <button className="btn btn-primary"> + Generate + </button> + </div> +}; + +export default function LipsyncEditor({ ...rest }) { + const audioProps = useFile({ debug: 'audio useFile' }); + const imageProps = useFile({}); + + const subText = "Select an image with a clear face, or one of our existing templates, then choose either text to speech or uploaded audio(eg. music). Then you can generate a beautifully lipsynced video."; + const headerProps = { + childProps: { audioFile: !audioProps.file, imageFile: !imageProps.file }, + titleComponent: Title, + subText, + showButtons: false + }; + + return <div> + <PageHeader { ...headerProps }/> + <div {...{ className: "container" }}> + <div {...{ className: "lipsync-editor panel" }}> + <div {...{ className: "grid-heading" }}> + <h5>Image</h5> + </div> + <div {...{ className: "grid-heading" }}> + <h5>Audio</h5> + </div> + <div {...{ className: "grid-square lipsync-audio" }}> + <ImageInput {...imageProps}/> + </div> + <div {...{ className: "grid-square" }}> + <AudioInput {...{ ...audioProps, hideActions: true } }/> + </div> + </div> + </div> + </div>; +}; \ No newline at end of file diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/index.tsx b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/index.tsx new file mode 100644 index 0000000000..02f8db5b47 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/LipsyncEditor/index.tsx @@ -0,0 +1 @@ +export { default } from './LipsyncEditor'; \ No newline at end of file diff --git a/packages/fakeyou.com/src/v2/view/pages/lipsync/index.tsx b/packages/fakeyou.com/src/v2/view/pages/lipsync/index.tsx new file mode 100644 index 0000000000..e9598cfc23 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/lipsync/index.tsx @@ -0,0 +1,3 @@ +import LipsyncEditor from './LipsyncEditor'; + +export { LipsyncEditor }; \ No newline at end of file