Skip to content

Commit

Permalink
Merge pull request #19 from cmgriffing/issue-9
Browse files Browse the repository at this point in the history
feat: add modal during audio processing
  • Loading branch information
cmgriffing authored Jan 23, 2024
2 parents 9857603 + de8f1e3 commit caf6076
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 13 deletions.
12 changes: 12 additions & 0 deletions src/components/CountingLoader.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.counting-loader {
position: relative;

.count {
position: absolute;
top: 0;
right: 0;
bottom: 6px;
left: 0;
font-weight: bold;
}
}
20 changes: 20 additions & 0 deletions src/components/CountingLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

Check failure on line 1 in src/components/CountingLoader.tsx

View workflow job for this annotation

GitHub Actions / Deploy

'React' is declared but its value is never read.
import { Loader, Flex } from "@mantine/core";

import "./CountingLoader.scss";

interface CountingLoaderProps {
count: number;
color: string;
}

export function CountingLoader({ count, color = "blue" }: CountingLoaderProps) {
return (
<div className="counting-loader">
<Loader color={color} />
<Flex className="count" align="center" justify={"center"}>
{count}
</Flex>
</div>
);
}
7 changes: 2 additions & 5 deletions src/components/SnippetForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ dayjs.extend(relativeTime);

import { SnippetModel } from "../data/repositories/snippets";

import "./SnippetForm.scss";
import {
SnippetStatus,
SnippetStatusIcon,
getSnippetStatus,
} from "./SnippetStatusIcon";

import "./SnippetForm.scss";

interface BaseSnippetProps {
bookId: string;
snippet: SnippetModel | undefined;
Expand Down Expand Up @@ -73,10 +74,6 @@ export function SnippetForm({
setContentValue(snippet?.content || "");
}, [snippet]);

console.log({ status });

console.log({ snippet });

const contents = (
<>
<Flex justify={"flex-end"}>
Expand Down
87 changes: 79 additions & 8 deletions src/routes/Snippet.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useRef, useState, startTransition } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { Flex, Button, Modal, Text, Loader } from "@mantine/core";
import { Flex, Button, Modal, Text } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { useAtom } from "jotai";
import {
Expand All @@ -13,6 +13,8 @@ import {
import { IconCirclePlus } from "@tabler/icons-react";
import { SnippetModel, SnippetsCRUD } from "../data/repositories/snippets";
import { SnippetForm } from "../components/SnippetForm";
import { CountingLoader } from "../components/CountingLoader";

import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
dayjs.extend(relativeTime);
Expand Down Expand Up @@ -45,6 +47,8 @@ export function Snippet() {
const contentRef = useRef<HTMLTextAreaElement>(null);
const [isRecording, setIsRecording] = useState(false);
const [recordingDuration, setRecordingDuration] = useState(0);
const [isProcessing, setIsProcessing] = useState(false);
const [processingDuration, setProcessingDuration] = useState(0);
const [whisper] = useAtom(whisperInstance);
const [audio, setAudio] = useState<Float32Array>(new Float32Array());
const [audioBlob, setAudioBlob] = useState<Blob>();
Expand All @@ -53,6 +57,15 @@ export function Snippet() {
const [previousSnippet, setPreviousSnippet] = useState<SnippetModel>();
const [nextSnippet, setNextSnippet] = useState<SnippetModel>();

const [
recordingModalOpened,
{ open: openRecordingModal, close: closeRecordingModal },
] = useDisclosure(false);
const [
processingModalOpened,
{ open: openProcessingModal, close: closeProcessingModal },
] = useDisclosure(false);

const [{ start: startRecording, stop: stopRecording }, setMicrophone] =
useState({
start: () => {},
Expand All @@ -75,7 +88,15 @@ export function Snippet() {
setAudioBlob(newAudioBlob);
const result = await whisper?.processAudio(newAudio);

console.log({ result });
if (result !== 0) {
// non-zero exit code found. report problem to user
// TODO: Make this something nicer than an alert
alert("Error processing audio");
} else {
setIsProcessing(true);
openProcessingModal();
// recommend refresh if taking too long and advise fine tuning threads
}
},
})
);
Expand Down Expand Up @@ -107,6 +128,9 @@ export function Snippet() {
processedAt: Date.now(),
});

setIsProcessing(false);
closeProcessingModal();

startTransition(() => {
setFetchTimestamp(Date.now());
});
Expand Down Expand Up @@ -140,10 +164,22 @@ export function Snippet() {
}
}, [isRecording]);

const [
recordingModalOpened,
{ open: openRecordingModal, close: closeRecordingModal },
] = useDisclosure(false);
useEffect(() => {
if (isProcessing) {
const processingStartedAt = Date.now();
setProcessingDuration(0);

const processingInterval = setInterval(() => {
setProcessingDuration(
Math.floor((Date.now() - processingStartedAt) / 1000)
);
}, 1000);

return () => {
clearInterval(processingInterval);
};
}
}, [isProcessing]);

useEffect(() => {
setCurrentSnippetId(snippetId);
Expand Down Expand Up @@ -304,9 +340,8 @@ export function Snippet() {
<Text size="xl" fw="bold">
Recording
</Text>
<Loader color="red" />
</Flex>
{isRecording && <Flex>{recordingDuration} seconds</Flex>}
<CountingLoader count={recordingDuration} color="red" />
<Button
color="red"
onClick={() => {
Expand All @@ -321,6 +356,42 @@ export function Snippet() {
</Button>
</Flex>
</Modal>

<Modal
opened={processingModalOpened}
closeOnClickOutside={false}
closeOnEscape={false}
withCloseButton={false}
onClose={() => {
// we shouldn't actually be able to get to here
closeProcessingModal();
}}
centered
size="auto"
padding={24}
>
<Flex direction="column" align="center" justify="center" gap={20}>
<Flex align="center" justify="center" gap={12}>
<Text size="xl" fw="bold">
Processing Audio
</Text>
</Flex>
<CountingLoader color="blue" count={processingDuration} />

{recordingDuration + 20 < processingDuration && (
<Flex maw={"300px"}>
<Text color="red">
This is taking longer than expected. You may want to fine tune
the amount of threads used by Whisper. It will often be
fastest with a couple less than the totally available cores.
</Text>
</Flex>
)}
<Flex maw={"300px"}>
If you would like to cancel the process, please refresh the page.
</Flex>
</Flex>
</Modal>
{/* DEBUG ELEMENTS */}
{/* <div>
<input
Expand Down

0 comments on commit caf6076

Please sign in to comment.