diff --git a/packages/fakeyou.com/src/scss/site-refresh.scss b/packages/fakeyou.com/src/scss/site-refresh.scss index fb4f557b0e..1e47b36e55 100644 --- a/packages/fakeyou.com/src/scss/site-refresh.scss +++ b/packages/fakeyou.com/src/scss/site-refresh.scss @@ -1158,6 +1158,14 @@ styles with important tags: } } + .file-size { + font-size: 14px; + color: rgba($white, 0.75); + padding: 4px 8px; + border-radius: 5px; + background-color: $secondary; + } + .nav-vc { flex-wrap: nowrap; height: auto; @@ -1311,6 +1319,10 @@ styles with important tags: font-weight: 500 !important; } + .bg-stepper { + background-color: lighten($panel, 4%); + } + .stepper-container { width: 100%; display: flex; @@ -1318,14 +1330,14 @@ styles with important tags: align-items: center; .stepper-number { - font-size: 16px; + font-size: 22px; font-weight: 600; display: flex; align-items: center; justify-content: center; - width: 32px; - height: 32px; - min-width: 32px; + width: 36px; + height: 36px; + min-width: 36px; background-color: $secondary; border-radius: 48px; opacity: 0.4; @@ -1354,6 +1366,7 @@ styles with important tags: height: 3px; background: $secondary; transition: all 0.2s; + min-width: 80px; &.active { background-color: $primary; @@ -1484,6 +1497,11 @@ textarea { padding: 2rem !important; } + .px-lg-4 { + padding-left: 2rem !important; + padding-right: 2rem !important; + } + .lead { font-size: 18px; } diff --git a/packages/fakeyou.com/src/v2/view/_common/Panel.tsx b/packages/fakeyou.com/src/v2/view/_common/Panel.tsx index dad7104cc4..93b0481cda 100644 --- a/packages/fakeyou.com/src/v2/view/_common/Panel.tsx +++ b/packages/fakeyou.com/src/v2/view/_common/Panel.tsx @@ -4,12 +4,15 @@ import { panel } from "data/animation"; interface PanelProps { children: React.ReactNode; + padding?: boolean; } function Panel(props: PanelProps) { return ( - - {props.children} + + + {props.children} + ); } diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerPage.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerPage.tsx index 5af063546c..7bd3def274 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerPage.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/VoiceDesignerPage.tsx @@ -54,12 +54,20 @@ function VoiceDesignerPage(this: any) { {/* Stepper */} - + + + - {displayStep(currentStep)} + {displayStep(currentStep)} {/* Navigation Controls */} - + + ); diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/Stepper.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/Stepper.tsx index 07029c37c6..70693e7dcd 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/Stepper.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/Stepper.tsx @@ -31,7 +31,7 @@ const Stepper: React.FC = ({ steps, currentStep }) => { {index !== steps.length - 1 && ( )} diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx index 19e2b53caa..f17fcd5180 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/StepperControls.tsx @@ -3,21 +3,34 @@ import React from "react"; interface StepperControlsProps { onBack: () => void; onNext: () => void; + steps: string[]; + currentStep: number; } const StepperControls: React.FC = ({ onBack, onNext, + steps, + currentStep, }) => { return ( - - - Back - - - Next - - + <> + {currentStep !== steps.length - 1 && ( + + {currentStep !== 0 && ( + + Back + + )} + + {currentStep !== steps.length - 1 && ( + + {currentStep !== steps.length - 2 ? "Continue" : "Create Voice"} + + )} + + )} + > ); }; diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/VoiceDesignerUploadComponent.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/VoiceDesignerUploadComponent.tsx new file mode 100644 index 0000000000..e25dd802c4 --- /dev/null +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/VoiceDesignerUploadComponent.tsx @@ -0,0 +1,168 @@ +import { + faFileArrowUp, + faFileAudio, + faTrash, + faWaveform, +} from "@fortawesome/pro-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import React, { useState } from "react"; +import { FileUploader } from "react-drag-drop-files"; +import { InputVcAudioPlayer } from "v2/view/_common/InputVcAudioPlayer"; +import { v4 as uuidv4 } from "uuid"; +import { + UploadAudio, + UploadAudioIsOk, + UploadAudioRequest, +} from "@storyteller/components/src/api/upload/UploadAudio"; + +const FILE_TYPES = ["MP3", "WAV", "FLAC", "OGG"]; + +interface Props { + setMediaUploadToken: (token?: string) => void; + formIsCleared: boolean; + setFormIsCleared: (cleared: boolean) => void; + setCanConvert: (canConvert: boolean) => void; + changeConvertIdempotencyToken: () => void; +} + +function VoiceDesignerUploadComponent(props: Props) { + const [files, setFiles] = useState([]); + const [audioLinks, setAudioLinks] = useState([]); + const [isUploadDisabled, setIsUploadDisabled] = useState(false); + + // Auto generated + const [idempotencyToken, setIdempotencyToken] = useState(uuidv4()); + + const handleChange = (file: any) => { + if (files.length < 20) { + setFiles([...files, file]); + setIdempotencyToken(uuidv4()); + const audioUrl = URL.createObjectURL(file); + setAudioLinks([...audioLinks, audioUrl ?? ""]); + props.setFormIsCleared(false); + props.setCanConvert(false); + props.changeConvertIdempotencyToken(); + setIsUploadDisabled(false); + } + }; + + const handleDragOver = (e: React.DragEvent): void => { + e.preventDefault(); + e.stopPropagation(); + e.currentTarget.classList.add("upload-zone-drag"); + }; + + const handleDragLeave = (e: React.DragEvent): void => { + e.preventDefault(); + e.stopPropagation(); + e.currentTarget.classList.remove("upload-zone-drag"); + }; + + const getFileSize = (file: any) => + file && file.size >= 1024 * 1024 + ? (file.size / 1024 / 1024).toFixed(2) + " MB" + : file + ? `${Math.floor(file.size / 1024)} KB` + : null; + + const uploadBtnClass = isUploadDisabled + ? "btn btn-uploaded w-100 disabled" + : "btn btn-primary w-100"; + + const handleRemoveFile = (index: number) => { + const updatedFiles = [...files]; + updatedFiles.splice(index, 1); + setFiles(updatedFiles); + + const updatedAudioLinks = [...audioLinks]; + updatedAudioLinks.splice(index, 1); + setAudioLinks(updatedAudioLinks); + }; + + return ( + + {/* Usage refer to https://github.com/KarimMokhtar/react-drag-drop-files */} + + + + + + + Upload files or drop them here... + + + + + {FILE_TYPES.join(", ").toString()} supported + + + + + + } + /> + + + Voice Samples ({files.length}/20) + + {files.length > 0 ? ( + + {files.map((file, index) => ( + + + + + {file.name} + {getFileSize(file)} + + handleRemoveFile(index)} + > + + Remove + + + + + + + ))} + + ) : ( + + + + No voice samples yet + Selected samples will appear here. + + + )} + + ); +} + +const LoadingIcon: React.FC = () => { + return ( + <> + + Loading... + > + ); +}; + +export default VoiceDesignerUploadComponent; diff --git a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/steps/UploadSamples.tsx b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/steps/UploadSamples.tsx index c35345dcf5..671e35bae0 100644 --- a/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/steps/UploadSamples.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/voice_designer/components/steps/UploadSamples.tsx @@ -1,9 +1,36 @@ -import React from "react"; +import React, { useState } from "react"; +import VoiceDesignerUploadComponent from "../VoiceDesignerUploadComponent"; +import { v4 as uuidv4 } from "uuid"; function UploadSamples() { + const [convertLoading, setConvertLoading] = useState(false); + const [canConvert, setCanConvert] = useState(false); + const [mediaUploadToken, setMediaUploadToken] = useState( + undefined + ); + const [convertIdempotencyToken, setConvertIdempotencyToken] = useState( + uuidv4() + ); + const [formIsCleared, setFormIsCleared] = useState(false); + + const changeConvertIdempotencyToken = () => { + setConvertIdempotencyToken(uuidv4()); + }; + return ( - - + + + Upload Audio + + + + ); }
+ {FILE_TYPES.join(", ").toString()} supported +
Selected samples will appear here.