diff --git a/src/website/package.json b/src/website/package.json
index 32ce1863e7..c5f197810d 100644
--- a/src/website/package.json
+++ b/src/website/package.json
@@ -34,10 +34,12 @@
"@babel/runtime": "^7.25.0",
"@react-spring/types": "^9.7.3",
"@typeform/embed": "^4.8.1",
+ "@types/dom-mediacapture-record": "^1.0.19",
"framer-motion": "6.5.1",
"local-storage": "^2.0.0",
"moment": "^2.29.4",
"react-easy-crop": "^5.0.7",
+ "react-webcam": "^7.2.0",
"universal-cookie": "^6.1.1",
"yarn": "^1.22.19"
},
diff --git a/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.scss b/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.scss
index 7f5f6839f0..7c39e7fda4 100644
--- a/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.scss
+++ b/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.scss
@@ -1,11 +1,6 @@
@import "scss/colours.scss";
@import "scss/site-refresh.scss";
-@mixin video-tint {
- background-color: rgba($secondary-very-dark, 0.5);
- backdrop-filter: blur(5px);
-}
-
.fy-slide-frame {
position: absolute;
height: 100%;
diff --git a/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.tsx b/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.tsx
index b87b281029..3b30d7d233 100644
--- a/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.tsx
+++ b/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInput.tsx
@@ -41,6 +41,7 @@ interface EntityInputProps {
name?: string;
onChange?: any;
onPromptUpdate?: (prompt: Prompt | null) => void;
+ showWebcam?: boolean;
type: EntityModeProp;
value?: string;
}
@@ -177,6 +178,7 @@ export default function EntityInput({
name = "",
onChange,
onPromptUpdate,
+ showWebcam = false,
type,
value,
...rest
@@ -305,6 +307,7 @@ export default function EntityInput({
onSelect,
queryUser,
render: EntityInputEmpty,
+ showWebcam,
type,
...sharedProps,
...rest,
diff --git a/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInputEmpty.tsx b/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInputEmpty.tsx
index f667dac857..6199669653 100644
--- a/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInputEmpty.tsx
+++ b/src/website/packages/fakeyou.com/src/components/entities/EntityInput/EntityInputEmpty.tsx
@@ -5,9 +5,11 @@ import {
useModal,
useSession,
} from "hooks";
-import MediaBrowser, {
+import {
+ CameraCapture,
+ MediaBrowser,
MediaBrowserProps,
-} from "components/modals/MediaBrowser";
+} from "components/modals";
import { FileWrapper } from "components/common";
import {
AcceptTypes,
@@ -20,6 +22,7 @@ import {
} from "components/entities/EntityTypes";
import { FontAwesomeIcon as Icon } from "@fortawesome/react-fontawesome";
import {
+ faCamera,
faDiagramSankey,
faFile,
faFileArrowUp,
@@ -33,6 +36,7 @@ interface EmptySlideProps extends SlideProps {
accept: AcceptTypes | AcceptTypes[];
inputProps?: any;
queryUser?: string;
+ showWebcam: boolean;
type: EntityModeProp;
}
@@ -40,6 +44,7 @@ export default function EntityInputEmpty({
accept,
inputProps,
queryUser,
+ showWebcam,
type,
...rest
}: EmptySlideProps) {
@@ -71,6 +76,13 @@ export default function EntityInputEmpty({
props,
});
+ const cameraClick = () =>
+ open({
+ component: CameraCapture,
+ padding: false,
+ width: "square",
+ });
+
const mediaIcons = () => {
if (isSelectedType(MediaFilters.audio, accepted[0])) return faWaveform;
if (isSelectedType(MediaFilters.engine_asset, accepted[0]))
@@ -130,6 +142,19 @@ export default function EntityInputEmpty({
/>
Choose from your {["bookmarks", "media", "weights"][inputMode]}
+ {showWebcam && (
+
+
+ Record with your camera
+
+ )}
>
);
diff --git a/src/website/packages/fakeyou.com/src/components/modals/CameraCapture/CameraCapture.scss b/src/website/packages/fakeyou.com/src/components/modals/CameraCapture/CameraCapture.scss
new file mode 100644
index 0000000000..adcd21e7ab
--- /dev/null
+++ b/src/website/packages/fakeyou.com/src/components/modals/CameraCapture/CameraCapture.scss
@@ -0,0 +1,59 @@
+@import "scss/colours.scss";
+@import "scss/site-refresh.scss";
+
+.fy-camera-capture-modal {
+ width: 100%;
+ height: 100%;
+
+ position: relative;
+
+ .fy-camera-capture-display {
+ height: 100%;
+ margin: auto;
+ }
+
+ .fy-camera-capture-controls {
+ @include video-tint;
+ position: absolute;
+ bottom: 1rem;
+ border-radius: 0.5rem;
+ padding: 0.5rem 0.5rem 0.25rem;
+ left: 0;
+ right: 0;
+ margin: auto;
+ width: 50%;
+ display: flex;
+ justify-content: center;
+ }
+
+ .fy-camera-capture-record-toggle {
+ appearance: none;
+ border: none;
+ background: none;
+ display: inline-flex;
+ justify-content: center;
+ flex-direction: column;
+ align-items: center;
+ color: #fff;
+ font-size: 0.75rem;
+
+ // background: green;
+
+ svg {
+ display: block;
+ // background: rgba(#00f, 0.25);
+ height: 2rem;
+ width: 2rem;
+ margin-bottom: 0.25rem;
+
+ circle {
+ fill: none;
+ stroke: $primary;
+ stroke-width: 2px;
+ }
+ rect {
+ fill: $primary;
+ }
+ }
+ }
+}
diff --git a/src/website/packages/fakeyou.com/src/components/modals/CameraCapture/CameraCapture.tsx b/src/website/packages/fakeyou.com/src/components/modals/CameraCapture/CameraCapture.tsx
new file mode 100644
index 0000000000..e22dd3d3c3
--- /dev/null
+++ b/src/website/packages/fakeyou.com/src/components/modals/CameraCapture/CameraCapture.tsx
@@ -0,0 +1,139 @@
+import React, { useCallback, useRef, useState } from "react";
+import Webcam from "react-webcam";
+import { a, useSpring } from "@react-spring/web";
+// import { MediaRecorder, IMediaRecorder } from "extendable-media-recorder";
+import "./CameraCapture.scss";
+
+import { ModalUtilities } from "components/common";
+
+// interface Props {
+// value?: any;
+// }
+
+export default function CameraCapture({ handleClose }: ModalUtilities) {
+ const webcamRef = useRef(null);
+ const mediaRecorderRef = useRef(null);
+ const [capturing, capturingSet] = useState(false);
+ const [recordedChunks, setRecordedChunks] = useState([]);
+
+ const handleDataAvailable = useCallback(
+ ({ data }) => {
+ if (data.size > 0) {
+ setRecordedChunks(prev => prev.concat(data));
+ }
+ },
+ [setRecordedChunks]
+ );
+
+ const handleDownload = React.useCallback(() => {
+ if (recordedChunks.length) {
+ const blob = new Blob(recordedChunks, {
+ type: "video/webm",
+ });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ document.body.appendChild(a);
+ // a.style = "display: none";
+ a.href = url;
+ a.download = "react-webcam-stream-capture.webm";
+ a.click();
+ window.URL.revokeObjectURL(url);
+ setRecordedChunks([]);
+ }
+ }, [recordedChunks]);
+
+ const mainToggleClick = () => {
+ if (!capturing) {
+ capturingSet(true);
+
+ if (webcamRef.current && webcamRef.current.stream) {
+ console.log("๐งข", webcamRef.current.stream);
+ mediaRecorderRef.current = new MediaRecorder(webcamRef.current.stream, {
+ mimeType: "video/webm",
+ });
+
+ mediaRecorderRef.current.addEventListener(
+ "dataavailable",
+ handleDataAvailable
+ );
+ mediaRecorderRef.current.start();
+ }
+ } else {
+ capturingSet(false);
+
+ if (mediaRecorderRef.current !== null) {
+ mediaRecorderRef.current.stop();
+ }
+ }
+ };
+
+ const mainToggleStyle = useSpring({
+ rx: capturing ? 1 : 8,
+ size: capturing ? 14 : 16,
+ xy: capturing ? 9 : 8,
+ });
+
+ return (
+
+
+
+
+ {recordedChunks.length > 0 && (
+
+ )}
+
+ {/* {capturing ? (
+
+ ) : (
+
+ )}
+ {recordedChunks.length > 0 && (
+
+ )}*/}
+
+ );
+}
diff --git a/src/website/packages/fakeyou.com/src/components/modals/CameraCapture/index.tsx b/src/website/packages/fakeyou.com/src/components/modals/CameraCapture/index.tsx
new file mode 100644
index 0000000000..bf9459aede
--- /dev/null
+++ b/src/website/packages/fakeyou.com/src/components/modals/CameraCapture/index.tsx
@@ -0,0 +1 @@
+export { default } from "./CameraCapture";
diff --git a/src/website/packages/fakeyou.com/src/components/modals/index.tsx b/src/website/packages/fakeyou.com/src/components/modals/index.tsx
index dc82713592..e786b275df 100644
--- a/src/website/packages/fakeyou.com/src/components/modals/index.tsx
+++ b/src/website/packages/fakeyou.com/src/components/modals/index.tsx
@@ -1,4 +1,7 @@
+import CameraCapture from "./CameraCapture";
import InferenceJobsModal from "./InferenceJobsModal";
-import MediaBrowser from "./MediaBrowser";
+import MediaBrowser, { MediaBrowserProps } from "./MediaBrowser";
-export { InferenceJobsModal, MediaBrowser };
\ No newline at end of file
+export { CameraCapture, InferenceJobsModal, MediaBrowser };
+
+export type { MediaBrowserProps };
diff --git a/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalLayer.scss b/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalLayer.scss
index 7109ef0be7..9eaf911443 100644
--- a/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalLayer.scss
+++ b/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalLayer.scss
@@ -37,6 +37,17 @@
.fy-modal-body-small {
width: 100%;
height: fit-content;
+ }
+
+ .fy-modal-body-square {
+ width: 75vh;
+ height: 75vh;
+ }
+
+ .fy-modal-body-wide,
+ .fy-modal-body-narrow,
+ .fy-modal-body-small,
+ .fy-modal-body-square {
overflow: hidden;
background-color: $panel;
border-color: lighten($panel, 8%) !important;
@@ -54,4 +65,8 @@
border-radius: 0;
}
}
+
+ .fy-modal-no-padding {
+ padding: 0;
+ }
}
diff --git a/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalLayer.tsx b/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalLayer.tsx
index 9e9148551b..48e1c76ed2 100644
--- a/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalLayer.tsx
+++ b/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalLayer.tsx
@@ -12,6 +12,7 @@ interface Props {
lockTint?: boolean;
modalOpen: boolean;
onModalCloseEnd: (x: any) => void;
+ padding?: boolean;
width?: ModalWidth;
}
@@ -23,6 +24,7 @@ export default function ModalLayer({
lockTint,
modalOpen,
onModalCloseEnd,
+ padding = true,
width = "wide",
}: Props) {
const mainClassName = "fy-modal-layer";
@@ -57,7 +59,13 @@ export default function ModalLayer({
},
}}
>
-
+
{Content && (
)}
diff --git a/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalProvider.tsx b/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalProvider.tsx
index 1740be51a5..dabac072d9 100644
--- a/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalProvider.tsx
+++ b/src/website/packages/fakeyou.com/src/components/providers/ModalProvider/ModalProvider.tsx
@@ -50,6 +50,7 @@ export default function ModalProvider({ children }: ModalProviderProps) {
lockTint: modalState?.lockTint,
modalOpen,
onModalCloseEnd,
+ padding: modalState?.padding,
width: modalState?.width,
}}
/>
diff --git a/src/website/packages/fakeyou.com/src/hooks/useModalState.tsx b/src/website/packages/fakeyou.com/src/hooks/useModalState.tsx
index 27f1036b60..59fec86e91 100644
--- a/src/website/packages/fakeyou.com/src/hooks/useModalState.tsx
+++ b/src/website/packages/fakeyou.com/src/hooks/useModalState.tsx
@@ -1,11 +1,12 @@
import { useEffect, useState } from "react";
import { isMobile } from "react-device-detect";
-export type ModalWidth = "wide" | "narrow" | "small";
+export type ModalWidth = "wide" | "narrow" | "small" | "square";
export interface ModalConfig {
component: React.ElementType;
lockTint?: boolean;
+ padding?: boolean;
props?: any;
width?: ModalWidth;
}
diff --git a/src/website/packages/fakeyou.com/src/scss/site-refresh.scss b/src/website/packages/fakeyou.com/src/scss/site-refresh.scss
index 719bda5553..75a07d3154 100644
--- a/src/website/packages/fakeyou.com/src/scss/site-refresh.scss
+++ b/src/website/packages/fakeyou.com/src/scss/site-refresh.scss
@@ -58,6 +58,11 @@ styles with important tags:
}
}
+@mixin video-tint {
+ background-color: rgba($secondary-very-dark, 0.5);
+ backdrop-filter: blur(5px);
+}
+
.fakeyou-refresh {
//- BS5 classnames -//
.object-fit-cover {
diff --git a/src/website/packages/fakeyou.com/src/v2/view/pages/dev_upload/DevMediaInput.tsx b/src/website/packages/fakeyou.com/src/v2/view/pages/dev_upload/DevMediaInput.tsx
index 4815a724a4..0b9124770c 100644
--- a/src/website/packages/fakeyou.com/src/v2/view/pages/dev_upload/DevMediaInput.tsx
+++ b/src/website/packages/fakeyou.com/src/v2/view/pages/dev_upload/DevMediaInput.tsx
@@ -1,11 +1,25 @@
import React, { useState } from "react";
import { EntityInput } from "components/entities";
-import { EntityFilterOptions, EntityInputMode, EntityModeProp, ListEntityFilters } from "components/entities/EntityTypes";
-import { useModal, useNotifications,
- // useSession
+import {
+ EntityFilterOptions,
+ EntityInputMode,
+ EntityModeProp,
+ ListEntityFilters,
+} from "components/entities/EntityTypes";
+import {
+ useModal,
+ useNotifications,
+ // useSession
} from "hooks";
import { InferenceJobsModal } from "components/modals";
-import { Button, Checkbox, NumberSlider, SegmentButtons, TempInput, TempSelect } from "components/common";
+import {
+ Button,
+ Checkbox,
+ NumberSlider,
+ SegmentButtons,
+ TempInput,
+ TempSelect,
+} from "components/common";
import { onChanger } from "resources";
import "./DevEntityInput.scss";
@@ -14,35 +28,37 @@ interface Props {
}
interface Yank {
- [key: string]: any[]
+ [key: string]: any[];
}
export default function DevMediaInput({ value }: Props) {
// const { studioAccessCheck } = useSession();
const { create } = useNotifications();
- const [mediaToken,mediaTokenSet] = useState();
- const [notTitle,notTitleSet] = useState("Notification Title");
- const [notContent,notContentSet] = useState("Notification Content");
- const [autoRemove,autoRemoveSet] = useState(true);
- const [btnCount,btnCountSet] = useState(0);
+ const [mediaToken, mediaTokenSet] = useState();
+ const [notTitle, notTitleSet] = useState("Notification Title");
+ const [notContent, notContentSet] = useState("Notification Content");
+ const [autoRemove, autoRemoveSet] = useState(true);
+ const [btnCount, btnCountSet] = useState(0);
const [mode, modeSet] = useState
("media");
- const yadda = Object.keys(EntityInputMode).filter(val => isNaN(Number(val))).reduce((obj,modeType,i) => {
- return {
- [modeType]: ListEntityFilters(i),
- ...obj
- };
- },{});
+ const yadda = Object.keys(EntityInputMode)
+ .filter(val => isNaN(Number(val)))
+ .reduce((obj, modeType, i) => {
+ return {
+ [modeType]: ListEntityFilters(i),
+ ...obj,
+ };
+ }, {});
const onChange = onChanger({
autoRemoveSet,
btnCountSet,
mediaTokenSet,
notContentSet,
- notTitleSet
+ notTitleSet,
});
- const [filters,filtersSet] = useState(yadda);
- const [owner,ownerSet] = useState("");
+ const [filters, filtersSet] = useState(yadda);
+ const [owner, ownerSet] = useState("");
// const onChange = ({ target }: any) => mediaTokenSet(target.value);
const { open } = useModal();
@@ -53,61 +69,104 @@ export default function DevMediaInput({ value }: Props) {
console.log("โ", mode, inputMode, filterOptions, filters[mode]);
- const changeFilter = ({ target }: { target: any }) => filtersSet({ ...filters, [mode]: target.value });
+ const changeFilter = ({ target }: { target: any }) =>
+ filtersSet({ ...filters, [mode]: target.value });
const openModal = () => open({ component: InferenceJobsModal });
const testBtn = { label: "abc" };
- const actions = Array.from({length: btnCount},() => testBtn);
+ const actions = Array.from({ length: btnCount }, () => testBtn);
- const createNotification = () => create({
- actions,
- autoRemove,
- title: notTitle,
- content: notContent,
- onClick: () => console.log("๐")
- });
+ const createNotification = () =>
+ create({
+ actions,
+ autoRemove,
+ title: notTitle,
+ content: notContent,
+ onClick: () => console.log("๐"),
+ });
- return (
-
{ [526,187].map((num = 0) => String.fromCodePoint(128000 + num)) }
-
-
-
-
-
-
-
-
+ return (
+
+
{[526, 187].map((num = 0) => String.fromCodePoint(128000 + num))}
+
+
+
Select Entities
+
+ modeSet(target.value),
+ options,
+ value: mode,
+ }}
+ />
+ ownerSet(target.value),
+ placeholder: "User",
+ }}
+ />
+
+
+
+
+
{mediaToken}
-
-
Select Entities
-
- modeSet(target.value), options, value: mode }}/>
- ownerSet(target.value), placeholder: "User" }}/>
-
-
-
-
-
- { mediaToken }
-
-
-
);
-};
\ No newline at end of file
+ );
+}
diff --git a/src/website/yarn.lock b/src/website/yarn.lock
index d0007a9692..36c1199a57 100644
--- a/src/website/yarn.lock
+++ b/src/website/yarn.lock
@@ -4487,6 +4487,7 @@ __metadata:
"@babel/runtime": ^7.25.0
"@react-spring/types": ^9.7.3
"@typeform/embed": ^4.8.1
+ "@types/dom-mediacapture-record": ^1.0.19
craco: ^0.0.3
cross-env: ^7.0.3
framer-motion: 6.5.1
@@ -4497,6 +4498,7 @@ __metadata:
prettier: ^3.1.0
pretty-quick: ^3.1.3
react-easy-crop: ^5.0.7
+ react-webcam: ^7.2.0
universal-cookie: ^6.1.1
yarn: ^1.22.19
languageName: unknown
@@ -5100,6 +5102,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/dom-mediacapture-record@npm:^1.0.19":
+ version: 1.0.19
+ resolution: "@types/dom-mediacapture-record@npm:1.0.19"
+ checksum: 4fb7b0bb7bcc6378fa9f0cfce2e144fcc41b5df3c7842bab07f6b812084bd41c18110ed27043ab28b24e2c251233fe4ae5ab0597e6b8509fef9647b29eed2d40
+ languageName: node
+ linkType: hard
+
"@types/eslint-scope@npm:^3.7.0":
version: 3.7.3
resolution: "@types/eslint-scope@npm:3.7.3"
@@ -18207,6 +18216,16 @@ __metadata:
languageName: node
linkType: hard
+"react-webcam@npm:^7.2.0":
+ version: 7.2.0
+ resolution: "react-webcam@npm:7.2.0"
+ peerDependencies:
+ react: ">=16.2.0"
+ react-dom: ">=16.2.0"
+ checksum: 55aecc9e33ea711525f9b68a7c14c9cf4089777b9edd6d9c93813568d701a101f3da09ffd7df04b64eca8c9783a37830522376049589699c6015555ec8d7ccd8
+ languageName: node
+ linkType: hard
+
"react@npm:^16.13.1":
version: 16.14.0
resolution: "react@npm:16.14.0"