diff --git a/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.tsx b/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.tsx index f1a58d7431..4e49094cb9 100644 --- a/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.tsx +++ b/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.tsx @@ -21,6 +21,7 @@ interface EntityInputProps { accept?: AcceptTypes | AcceptTypes[]; aspectRatio?: "square" | "landscape" | "portrait"; className?: string; + debug?: string; label?: string; name?: string; onChange?: any; @@ -136,6 +137,7 @@ export default function EntityInput({ accept, aspectRatio = "square", className, + debug, label, name = "", onChange, @@ -149,7 +151,14 @@ export default function EntityInput({ const presetToken = search ? urlSearch.get("preset_token") : ""; const queryUser = search ? urlSearch.get("query_user") : ""; const [mediaToken, mediaTokenSet] = useState(presetToken || value || ""); - const { media, mediaSet, prompt } = useMedia({ + const { + busy: mediaBusy, + media, + mediaSet, + prompt, + reload, + } = useMedia({ + debug, mediaToken: mediaToken || value, }); const [updated, updatedSet] = useState(false); @@ -163,9 +172,12 @@ export default function EntityInput({ onChange({ target: { name, value: token } }); }; - const { inputProps } = useMediaUploader({ + const { busy: uploaderBusy, inputProps } = useMediaUploader({ autoUpload: true, - onSuccess: (res: UploaderResponse) => selectToken(res.media_file_token), + onSuccess: (res: UploaderResponse) => { + reload(); + selectToken(res.media_file_token); + }, }); const onSelect = (data: MediaFile) => { @@ -173,10 +185,18 @@ export default function EntityInput({ selectToken(data.token); }; - const busy = false; + const busy = mediaBusy || uploaderBusy; const index = busy ? 0 : media ? 1 : 2; const [animating, animatingSet] = useState(false); + if (debug) + console.log(`🐞 EntityInput Debug at ${debug}`, { + index, + busy, + media, + view: ["busy slide", "full slide", "empty slide"][index], + }); + const transitions = useTransition(index, { config: { mass: 1, tension: 80, friction: 10 }, from: { opacity: 0, transform: `translateX(${5}rem)` }, @@ -219,7 +239,8 @@ export default function EntityInput({ return [ {}, onRemove = (res: any) => {}, @@ -20,6 +20,7 @@ export default function useMedia({ const [writeStatus, writeStatusSet] = useState(FetchStatus.paused); const [media, mediaSet] = useState(); const [prompt, promptSet] = useState(); + const remove = (as_mod: boolean) => { writeStatusSet(FetchStatus.in_progress); DeleteMedia(mediaToken, { @@ -31,19 +32,20 @@ export default function useMedia({ }); }; - const previousToken = usePrevious(mediaToken); - const reload = () => { statusSet(FetchStatus.ready); mediaSet(undefined); }; + const busy = + status === FetchStatus.in_progress || + writeStatus === FetchStatus.in_progress; + useEffect(() => { - if ( - status === FetchStatus.ready && - mediaToken && - (!media || previousToken !== mediaToken) - ) { + // this condidition handles all media file fetches + // it is triggered when status is ready and there is a media token but no media + + if (status === FetchStatus.ready && mediaToken && !media) { statusSet(FetchStatus.in_progress); GetMedia(mediaToken, {}) .then(res => { @@ -51,6 +53,7 @@ export default function useMedia({ statusSet(FetchStatus.success); onSuccess(res.media_file); mediaSet(res.media_file); + if (res.media_file.maybe_prompt_token) { GetPrompts(res.media_file.maybe_prompt_token, {}).then( promptRes => { @@ -67,13 +70,16 @@ export default function useMedia({ }); } + // this triggers a media refetch when there is media, but the hook mediaToken param is updated + if (media && media.token !== mediaToken) { mediaSet(undefined); statusSet(FetchStatus.ready); } - }, [media, mediaToken, previousToken, prompt, onSuccess, status, statusSet]); + }, [media, mediaToken, prompt, onSuccess, status, statusSet]); return { + busy, media, mediaFile: media, mediaSet, @@ -81,6 +87,7 @@ export default function useMedia({ remove, reload, status, + statusSet, writeStatus, }; } diff --git a/packages/fakeyou.com/src/hooks/useMediaUploader/useMediaUploader.tsx b/packages/fakeyou.com/src/hooks/useMediaUploader/useMediaUploader.tsx index d33c224485..f439adf36f 100644 --- a/packages/fakeyou.com/src/hooks/useMediaUploader/useMediaUploader.tsx +++ b/packages/fakeyou.com/src/hooks/useMediaUploader/useMediaUploader.tsx @@ -1,36 +1,56 @@ import { useState } from "react"; import { useFile } from "hooks"; import { v4 as uuidv4 } from "uuid"; -import { isSelectedType, MediaFilters, UploaderResponse } from "components/entities/EntityTypes"; +import { + isSelectedType, + MediaFilters, + UploaderResponse, +} from "components/entities/EntityTypes"; import { UploadMedia } from "@storyteller/components/src/api/media_files/UploadMedia"; -import { UploadEngineAsset }from "@storyteller/components/src/api/media_files/UploadEngineAsset"; +import { UploadEngineAsset } from "@storyteller/components/src/api/media_files/UploadEngineAsset"; import { MediaFileSubtype } from "@storyteller/components/src/api/enums/MediaFileSubtype"; import { GetFileTypeByExtension as extension } from "@storyteller/components/src/utils/GetFileTypeByExtension"; import { MediaFileClass } from "@storyteller/components/src/api/enums/MediaFileClass"; +import { FetchStatus } from "@storyteller/components/src/api/_common/SharedFetchTypes"; interface Props { - autoUpload?: boolean, + autoUpload?: boolean; onSuccess?: (res: UploaderResponse) => any; } const n = () => {}; export default function useMediaUploader({ autoUpload, onSuccess = n }: Props) { - const [mediaClass,mediaClassSet] = useState(MediaFileClass.Unknown); - const [engineSubtype,engineSubtypeSet] = useState(); + const [status, statusSet] = useState(FetchStatus.ready); + const [mediaClass, mediaClassSet] = useState( + MediaFileClass.Unknown + ); + const [engineSubtype, engineSubtypeSet] = useState< + MediaFileSubtype | undefined + >(); - const createUpload = (inputFile: File, todo = n ) => { + const createUpload = (inputFile: File, todo = n) => { + statusSet(FetchStatus.in_progress); const fileExtension = extension(inputFile.name || ""); - const isEngineAsset = isSelectedType(MediaFilters.engine_asset, fileExtension); + const isEngineAsset = isSelectedType( + MediaFilters.engine_asset, + fileExtension + ); const baseConfig = { uuid_idempotency_token: uuidv4(), file: inputFile }; - const engineConfig = { ...baseConfig, media_file_subtype: engineSubtype, media_file_class: mediaClass }; + const engineConfig = { + ...baseConfig, + media_file_subtype: engineSubtype, + media_file_class: mediaClass, + }; const mediaConfig = { ...baseConfig, source: "file" }; - const uploader = isEngineAsset ? UploadEngineAsset(engineConfig) : UploadMedia(mediaConfig); + const uploader = isEngineAsset + ? UploadEngineAsset(engineConfig) + : UploadMedia(mediaConfig); if (inputFile) { - uploader - .then((res: UploaderResponse) => { + uploader.then((res: UploaderResponse) => { if ("media_file_token" in res) { + statusSet(FetchStatus.success); onSuccess(res); todo(); } @@ -39,16 +59,27 @@ export default function useMediaUploader({ autoUpload, onSuccess = n }: Props) { }; const { file, clear, inputProps } = useFile({ - ...autoUpload ? { onChange: (inputFile: File) => createUpload(inputFile,clear) } : {} + ...(autoUpload + ? { + onChange: (inputFile: File) => { + if (inputFile) createUpload(inputFile, clear); + }, + } + : {}), }); - const upload = () => createUpload(file,clear); + const upload = () => { + createUpload(file, clear); + }; - const engineSubtypeChange = ({ target }: { target: any }) => engineSubtypeSet(target.value); + const engineSubtypeChange = ({ target }: { target: any }) => + engineSubtypeSet(target.value); - const mediaClassChange = ({ target }: { target: any }) => mediaClassSet(target.value); + const mediaClassChange = ({ target }: { target: any }) => + mediaClassSet(target.value); return { + busy: status === FetchStatus.in_progress, clear, engineSubtype, engineSubtypeChange, @@ -57,10 +88,12 @@ export default function useMediaUploader({ autoUpload, onSuccess = n }: Props) { file, inputProps, isAudio: isSelectedType(MediaFilters.audio, extension(file?.name || "")), - isEngineAsset: isSelectedType(MediaFilters.engine_asset, extension(file?.name || "")), + isEngineAsset: isSelectedType( + MediaFilters.engine_asset, + extension(file?.name || "") + ), isImage: isSelectedType(MediaFilters.image, extension(file?.name || "")), isVideo: isSelectedType(MediaFilters.video, extension(file?.name || "")), - upload - } - -}; \ No newline at end of file + upload, + }; +} diff --git a/packages/fakeyou.com/src/v2/view/pages/ai_face_mirror/AIFaceMirror.tsx b/packages/fakeyou.com/src/v2/view/pages/ai_face_mirror/AIFaceMirror.tsx index e69775b852..41b5b46cbb 100644 --- a/packages/fakeyou.com/src/v2/view/pages/ai_face_mirror/AIFaceMirror.tsx +++ b/packages/fakeyou.com/src/v2/view/pages/ai_face_mirror/AIFaceMirror.tsx @@ -127,6 +127,7 @@ export default function AIFaceMirror({ sessionSubscriptionsWrapper }: Props) { {...{ accept: ["video"], aspectRatio: "landscape", + // debug: "AFM driver input", name: "faceDriverToken", value: faceDriverToken, onChange: ({ target }: { target: any }) => {