diff --git a/client/src/components/RecordingOptions/RecordingOptions.lazy.tsx b/client/src/components/RecordingOptions/RecordingOptions.lazy.tsx new file mode 100644 index 0000000..398b26b --- /dev/null +++ b/client/src/components/RecordingOptions/RecordingOptions.lazy.tsx @@ -0,0 +1,11 @@ +import React, { lazy, Suspense } from 'react'; + +const LazyRecordingOptions = lazy(() => import('./RecordingOptions')); + +const RecordingOptions = (props: JSX.IntrinsicAttributes & { children?: React.ReactNode; }) => ( + + + +); + +export default RecordingOptions; diff --git a/client/src/components/RecordingOptions/RecordingOptions.module.scss b/client/src/components/RecordingOptions/RecordingOptions.module.scss new file mode 100644 index 0000000..32801c1 --- /dev/null +++ b/client/src/components/RecordingOptions/RecordingOptions.module.scss @@ -0,0 +1 @@ +.RecordingOptions {} \ No newline at end of file diff --git a/client/src/components/RecordingOptions/RecordingOptions.stories.tsx b/client/src/components/RecordingOptions/RecordingOptions.stories.tsx new file mode 100644 index 0000000..6bb55d8 --- /dev/null +++ b/client/src/components/RecordingOptions/RecordingOptions.stories.tsx @@ -0,0 +1,12 @@ +/* eslint-disable */ +import RecordingOptions from './RecordingOptions'; + +export default { + title: "RecordingOptions", +}; + +export const Default = () => ; + +Default.story = { + name: 'default', +}; diff --git a/client/src/components/RecordingOptions/RecordingOptions.test.tsx b/client/src/components/RecordingOptions/RecordingOptions.test.tsx new file mode 100644 index 0000000..d0f897a --- /dev/null +++ b/client/src/components/RecordingOptions/RecordingOptions.test.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import RecordingOptions from './RecordingOptions'; + +describe('', () => { + test('it should mount', () => { + render(); + + const recordingOptions = screen.getByTestId('RecordingOptions'); + + expect(recordingOptions).toBeInTheDocument(); + }); +}); \ No newline at end of file diff --git a/client/src/components/RecordingOptions/RecordingOptions.tsx b/client/src/components/RecordingOptions/RecordingOptions.tsx new file mode 100644 index 0000000..85b88c7 --- /dev/null +++ b/client/src/components/RecordingOptions/RecordingOptions.tsx @@ -0,0 +1,32 @@ +import React, { FC, useContext } from 'react'; +import { Button, Container } from '@mui/material'; +import styles from './RecordingOptions.module.scss'; +import { FiberManualRecord, Stop } from '@mui/icons-material'; +import { HeadsetContext } from '../../contexts/HeadsetContext'; + +const RecordingOptions: FC<{}> = () => { + const { headset, isRecording, startRecording, stopRecording } = + useContext(HeadsetContext); + return ( + + {!isRecording ? ( + + ) : ( + + )} + + ); +}; + +export default RecordingOptions; diff --git a/client/src/contexts/HeadsetContext.tsx b/client/src/contexts/HeadsetContext.tsx index 405e106..7d1dd63 100644 --- a/client/src/contexts/HeadsetContext.tsx +++ b/client/src/contexts/HeadsetContext.tsx @@ -1,10 +1,11 @@ import React, { createContext, FC, useEffect, useState } from 'react'; -import { HeadsetDataWorkerResponse } from '../workers/headset-data-worker'; +import { HeadsetRecordingWorkerResponse } from '../workers/headset-recording-worker'; interface HeadsetContextExports { headset: BluetoothDevice | undefined; setHeadset: (headset: BluetoothDevice | undefined) => void; headsetData: number[][]; + isRecording: boolean; startRecording: () => void; stopRecording: () => void; } @@ -13,13 +14,17 @@ export const HeadsetContext = createContext({ headset: undefined, setHeadset: () => {}, headsetData: Array(8).fill(Array(60).fill(0)), + isRecording: false, startRecording: () => {}, stopRecording: () => {}, }); -const headsetDataWorker = new Worker('../workers/headset-data-worker.ts', { - type: 'module', -}); +const headsetRecordingWorker = new Worker( + '../workers/headset-recording-worker.ts', + { + type: 'module', + }, +); const HeadsetProvider: FC<{}> = ({ children }) => { const [headset, setHeadset] = useState( @@ -28,44 +33,50 @@ const HeadsetProvider: FC<{}> = ({ children }) => { const [headsetData, setHeadsetData] = useState( Array(8).fill(Array(60).fill(0)), ); + const [isRecording, setIsRecording] = useState(false); const [headsetReadingTask, setHeadsetReadingTask] = useState< NodeJS.Timer | undefined >(undefined); useEffect(() => { - headset - ? setHeadsetReadingTask( - setInterval(async () => { - // TODO: replace with actual headset data reading - const reading = Array(8).fill( - Array(60).fill(headsetData[0][0] + 1), - ); + if (headset) { + setHeadsetReadingTask( + setInterval(async () => { + // TODO: replace with actual headset data reading + const reading = Array(8).fill(Array(60).fill(headsetData[0][0] + 1)); - setHeadsetData(reading); - headsetDataWorker.postMessage({ - eventType: 'data', - headsetData, - }); - }, 8), - ) - : headsetReadingTask && clearInterval(headsetReadingTask); - console.log(headsetReadingTask); + setHeadsetData(reading); + headsetRecordingWorker.postMessage({ + eventType: 'data', + headsetData, + }); + }, 8), + ); + } else { + stopRecording(); + headsetReadingTask && clearInterval(headsetReadingTask); + } }, [headset]); const startRecording = () => { - headsetDataWorker.postMessage({ - eventType: 'record-start', + if (!headset) { + return; + } + setIsRecording(true); + headsetRecordingWorker.postMessage({ + eventType: 'start', }); }; const stopRecording = () => { - headsetDataWorker.postMessage({ - eventType: 'record-stop', + setIsRecording(false); + headsetRecordingWorker.postMessage({ + eventType: 'stop', }); }; - headsetDataWorker.onmessage = ( - event: MessageEvent, + headsetRecordingWorker.onmessage = ( + event: MessageEvent, ) => { // TODO: Post recording to the backend console.log(event.data.headsetRecording); @@ -77,6 +88,7 @@ const HeadsetProvider: FC<{}> = ({ children }) => { headset, setHeadset, headsetData, + isRecording, startRecording, stopRecording, }} diff --git a/client/src/workers/headset-data-worker.ts b/client/src/workers/headset-data-worker.ts deleted file mode 100644 index f09c209..0000000 --- a/client/src/workers/headset-data-worker.ts +++ /dev/null @@ -1,31 +0,0 @@ -let isRecording = false; -const headsetRecording: number[][][] = []; - -export interface HeadsetDataWorkerRequest { - eventType: 'data' | 'record-start' | 'record-stop'; - headsetData?: number[][]; -} - -export interface HeadsetDataWorkerResponse { - headsetRecording: number[][][]; -} - -addEventListener('message', (event: MessageEvent) => { - const { eventType, headsetData } = event.data; - console.log({ eventType, headsetData }); - - switch (eventType) { - case 'data': - isRecording && headsetData && headsetRecording.push(headsetData); - break; - - case 'record-start': - isRecording = true; - break; - - case 'record-stop': - isRecording = false; - postMessage({ headsetRecording }); - break; - } -}); diff --git a/client/src/workers/headset-recording-worker.ts b/client/src/workers/headset-recording-worker.ts new file mode 100644 index 0000000..f9ea44d --- /dev/null +++ b/client/src/workers/headset-recording-worker.ts @@ -0,0 +1,33 @@ +let isRecording = false; +const headsetRecording: number[][][] = []; + +export interface HeadsetRecordingWorkerRequest { + eventType: 'data' | 'start' | 'stop'; + headsetData?: number[][]; +} + +export interface HeadsetRecordingWorkerResponse { + headsetRecording: number[][][]; +} + +addEventListener( + 'message', + (event: MessageEvent) => { + const { eventType, headsetData } = event.data; + + switch (eventType) { + case 'data': + isRecording && headsetData && headsetRecording.push(headsetData); + break; + + case 'start': + isRecording = true; + break; + + case 'stop': + isRecording = false; + postMessage({ headsetRecording }); + break; + } + }, +);