Skip to content

Instantly share code, notes, and snippets.

@SandroMaglione
Created September 25, 2024 10:46
Show Gist options
  • Save SandroMaglione/2dd680cd04ec5f43b7e107ee01cca81d to your computer and use it in GitHub Desktop.
Save SandroMaglione/2dd680cd04ec5f43b7e107ee01cca81d to your computer and use it in GitHub Desktop.
import { assign, setup } from "xstate";
type Context = {
chunks: Blob[];
mediaRecorder?: MediaRecorder;
submit: (contents: { file: File }) => void;
};
type Events =
| {
type: "RECORD_TOGGLE_CLICKED";
}
| {
type: "NEW_CHUNK";
blob: Blob;
};
export const recordingMachine = setup({
types: {
context: {} as Context,
events: {} as Events,
input: {} as {
submit: (contents: { file: File }) => void;
},
},
actions: {
submitChunks: (x) => {
const blob = new Blob(x.context.chunks, {
type: "audio/ogg; codecs=opus",
});
const file = new File([blob], "filename.ogg");
x.context.submit({ file });
},
stopRecorder: (x) => {
x.context.mediaRecorder?.stop();
},
resetChunks: assign((x) => {
return {
chunks: [],
};
}),
assignNewChunk: assign((x, { blob }: { blob: Blob }) => {
return {
chunks: [...x.context.chunks, blob],
};
}),
},
}).createMachine({
initial: "idle",
context: ({ input }) => ({
submit: input.submit,
chunks: [],
}),
on: {
NEW_CHUNK: {
actions: {
type: "assignNewChunk",
params: ({ event }) => event,
},
},
},
states: {
idle: {
on: {
RECORD_TOGGLE_CLICKED: "recording",
},
},
recording: {
entry: ["resetChunks"],
exit: ["stopRecorder"],
on: {
RECORD_TOGGLE_CLICKED: {
target: "receivingFinalChunk",
},
},
},
receivingFinalChunk: {
on: {
NEW_CHUNK: {
actions: [
{
type: "assignNewChunk",
params: ({ event }) => event,
},
"submitChunks",
],
target: "idle",
},
},
},
errored: {},
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment