diff --git a/apps/frontend/src/components/launches/ai.video.tsx b/apps/frontend/src/components/launches/ai.video.tsx index b952579b..84ac317d 100644 --- a/apps/frontend/src/components/launches/ai.video.tsx +++ b/apps/frontend/src/components/launches/ai.video.tsx @@ -12,6 +12,8 @@ import { FormProvider, useForm } from 'react-hook-form'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; import { VideoContextWrapper } from '@gitroom/frontend/components/videos/video.context.wrapper'; import { useToaster } from '@gitroom/react/toaster/toaster'; +import { useModals } from '@gitroom/frontend/components/layout/new-modal'; +import { createPortal } from 'react-dom'; export const Modal: FC<{ close: () => void; @@ -73,71 +75,42 @@ export const Modal: FC<{ onSubmit={form.handleSubmit(generate)} className="flex flex-col gap-[10px]" > + {createPortal( + <>{data?.credits || 0} credits left, + document.querySelector('.top-title-content') || document.createElement('div') + )} -
-
-
-
-
- -
- {data?.credits || 0} credits left -
-
-
- -
-
-
-
-
- -
-
- -
-
- + Vertical (Stories, Reels) + +
+
+
-
- -
+
+
+ +
@@ -153,9 +126,9 @@ export const AiVideo: FC<{ const { value, onChange } = props; const [loading, setLoading] = useState(false); const [type, setType] = useState(null); - const [modal, setModal] = useState(false); const fetch = useFetch(); const { isTrailing } = useUser(); + const modals = useModals(); const loadVideoList = useCallback(async () => { return (await (await fetch('/media/video-options')).json()).filter( @@ -175,7 +148,21 @@ export const AiVideo: FC<{ const generateVideo = useCallback( (type: { identifier: string }) => async () => { setType(type); - setModal(true); + modals.openModal({ + title:
, + children: (close) => ( + { + close(); + setType(null); + }} + type={type} + value={value} + /> + ), + }); }, [value, onChange] ); @@ -186,18 +173,6 @@ export const AiVideo: FC<{ return ( <> - {modal && ( - { - setModal(false); - setType(null); - }} - type={type} - value={props.value} - /> - )}
-
{t('ai', 'AI')} Video
+
+ {t('ai', 'AI')} Video +
{value.length >= 30 && !loading && ( diff --git a/apps/frontend/src/components/layout/new-modal.tsx b/apps/frontend/src/components/layout/new-modal.tsx index 651e3e77..fdc3704a 100644 --- a/apps/frontend/src/components/layout/new-modal.tsx +++ b/apps/frontend/src/components/layout/new-modal.tsx @@ -17,7 +17,7 @@ import clsx from 'clsx'; import { EventEmitter } from 'events'; interface OpenModalInterface { - title?: string; + title?: any; closeOnClickOutside?: boolean; removeLayout?: boolean; fullScreen?: boolean; diff --git a/libraries/nestjs-libraries/src/upload/cloudflare.storage.ts b/libraries/nestjs-libraries/src/upload/cloudflare.storage.ts index cac8a803..1ada0ac7 100644 --- a/libraries/nestjs-libraries/src/upload/cloudflare.storage.ts +++ b/libraries/nestjs-libraries/src/upload/cloudflare.storage.ts @@ -18,6 +18,10 @@ const ALLOWED_MIME_TYPES = new Set([ 'image/bmp', 'image/tiff', 'video/mp4', + 'audio/mpeg', + 'audio/mp4', + 'audio/wav', + 'audio/ogg', ]); class CloudflareStorage implements IUploadProvider { diff --git a/libraries/nestjs-libraries/src/upload/local.storage.ts b/libraries/nestjs-libraries/src/upload/local.storage.ts index 6d8007bb..90cc42c5 100644 --- a/libraries/nestjs-libraries/src/upload/local.storage.ts +++ b/libraries/nestjs-libraries/src/upload/local.storage.ts @@ -15,6 +15,10 @@ const LOCAL_STORAGE_ALLOWED_MIME = new Set([ 'image/bmp', 'image/tiff', 'video/mp4', + 'audio/mpeg', + 'audio/mp4', + 'audio/wav', + 'audio/ogg', ]); export class LocalStorage implements IUploadProvider { constructor(private uploadDirectory: string) {}