Skip to content

Commit

Permalink
[Feat] RecordingOptions + disconnect stops worker
Browse files Browse the repository at this point in the history
Created RecordingOptions component to start or stop data recording.
Modified worker to stop on headset disconnect.
References #25, #27.
  • Loading branch information
angel-penchev committed Oct 26, 2021
1 parent 1f00bf2 commit 41d6ebf
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 57 deletions.
11 changes: 11 additions & 0 deletions client/src/components/RecordingOptions/RecordingOptions.lazy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, { lazy, Suspense } from 'react';

const LazyRecordingOptions = lazy(() => import('./RecordingOptions'));

const RecordingOptions = (props: JSX.IntrinsicAttributes & { children?: React.ReactNode; }) => (
<Suspense fallback={null}>
<LazyRecordingOptions {...props} />
</Suspense>
);

export default RecordingOptions;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.RecordingOptions {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* eslint-disable */
import RecordingOptions from './RecordingOptions';

export default {
title: "RecordingOptions",
};

export const Default = () => <RecordingOptions />;

Default.story = {
name: 'default',
};
14 changes: 14 additions & 0 deletions client/src/components/RecordingOptions/RecordingOptions.test.tsx
Original file line number Diff line number Diff line change
@@ -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('<RecordingOptions />', () => {
test('it should mount', () => {
render(<RecordingOptions />);

const recordingOptions = screen.getByTestId('RecordingOptions');

expect(recordingOptions).toBeInTheDocument();
});
});
32 changes: 32 additions & 0 deletions client/src/components/RecordingOptions/RecordingOptions.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<Container
className={styles.RecordingOptions}
data-testid="RecordingOptions"
>
{!isRecording ? (
<Button
disabled={!headset}
variant="outlined"
onClick={() => startRecording()}
>
<FiberManualRecord /> Record
</Button>
) : (
<Button variant="outlined" onClick={() => stopRecording()}>
<Stop /> Stop
</Button>
)}
</Container>
);
};

export default RecordingOptions;
64 changes: 38 additions & 26 deletions client/src/contexts/HeadsetContext.tsx
Original file line number Diff line number Diff line change
@@ -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;
}
Expand All @@ -13,13 +14,17 @@ export const HeadsetContext = createContext<HeadsetContextExports>({
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<BluetoothDevice | undefined>(
Expand All @@ -28,44 +33,50 @@ const HeadsetProvider: FC<{}> = ({ children }) => {
const [headsetData, setHeadsetData] = useState<number[][]>(
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<HeadsetDataWorkerResponse>,
headsetRecordingWorker.onmessage = (
event: MessageEvent<HeadsetRecordingWorkerResponse>,
) => {
// TODO: Post recording to the backend
console.log(event.data.headsetRecording);
Expand All @@ -77,6 +88,7 @@ const HeadsetProvider: FC<{}> = ({ children }) => {
headset,
setHeadset,
headsetData,
isRecording,
startRecording,
stopRecording,
}}
Expand Down
31 changes: 0 additions & 31 deletions client/src/workers/headset-data-worker.ts

This file was deleted.

33 changes: 33 additions & 0 deletions client/src/workers/headset-recording-worker.ts
Original file line number Diff line number Diff line change
@@ -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<HeadsetRecordingWorkerRequest>) => {
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;
}
},
);

0 comments on commit 41d6ebf

Please sign in to comment.