-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6c5aa02
commit 14216a9
Showing
6 changed files
with
204 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import { useEnsureRegeneratorRuntime } from "@/app/hooks/useEnsureRegeneratorRuntime"; | ||
import { Textarea } from "@/components/ui/textarea"; | ||
import { useEffect, useRef } from "react"; | ||
import { Grid } from "react-loader-spinner"; | ||
import SpeechRecognition, { | ||
useSpeechRecognition, | ||
} from "react-speech-recognition"; | ||
import { MicIcon } from "../icons/mic-icon"; | ||
import { XIcon } from "../icons/x-icon"; | ||
import { Button } from "../ui/button"; | ||
import { toast } from "../ui/use-toast"; | ||
|
||
interface SendForm { | ||
input: string; | ||
handleSubmit: (event: React.FormEvent<HTMLFormElement>) => void; | ||
isLoading: boolean; | ||
handleInputChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => void; | ||
} | ||
|
||
export default function SendForm({ | ||
input, | ||
handleSubmit, | ||
isLoading, | ||
handleInputChange, | ||
}: SendForm) { | ||
useEnsureRegeneratorRuntime(); | ||
|
||
const textareaRef = useRef(null); | ||
const { | ||
listening, | ||
browserSupportsSpeechRecognition, | ||
resetTranscript, | ||
transcript, | ||
} = useSpeechRecognition(); | ||
|
||
useEffect(() => { | ||
if (!browserSupportsSpeechRecognition) { | ||
toast({ | ||
description: "Your browser does not support speech recognition", | ||
}); | ||
} | ||
}, [browserSupportsSpeechRecognition]); | ||
|
||
useEffect(() => { | ||
if (listening) { | ||
const textarea = document.querySelector(".mendable-textarea"); | ||
if (textarea) { | ||
textarea.scrollTop = textarea.scrollHeight; | ||
} | ||
} | ||
}, [listening, input]); | ||
|
||
// This listener stops the speech recognition when the tab is not visible | ||
useEffect(() => { | ||
const handleVisibilityChange = () => { | ||
if (document.visibilityState === "hidden" && listening) { | ||
SpeechRecognition.stopListening(); | ||
} | ||
}; | ||
|
||
document.addEventListener("visibilitychange", handleVisibilityChange); | ||
|
||
return () => { | ||
document.removeEventListener("visibilitychange", handleVisibilityChange); | ||
}; | ||
}, [listening]); | ||
|
||
useEffect(() => { | ||
if (transcript) { | ||
updateInputWithTranscript(transcript); | ||
} | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [transcript]); | ||
|
||
const updateInputWithTranscript = (transcriptValue: string) => { | ||
const fakeEvent: any = { | ||
target: { value: transcriptValue }, | ||
}; | ||
handleInputChange(fakeEvent); | ||
}; | ||
|
||
function toggleSpeech() { | ||
if (listening) { | ||
SpeechRecognition.stopListening(); | ||
return; | ||
} else { | ||
SpeechRecognition.startListening({ continuous: true }); | ||
return; | ||
} | ||
} | ||
|
||
return ( | ||
<form | ||
onSubmit={(event) => { | ||
handleSubmit(event); | ||
}} | ||
className="flex items-center justify-center w-full space-x-2" | ||
> | ||
<div className="relative w-full max-w-xs"> | ||
<MicIcon | ||
onClick={toggleSpeech} | ||
className={`absolute right-2 h-4 w-4 top-1/2 transform -translate-y-2 ${ | ||
listening ? "text-red-500 scale-125 animate-pulse" : "text-gray-500" | ||
} dark:text-gray-400 hover:scale-125 cursor-pointer`} | ||
/> | ||
<XIcon | ||
onClick={() => { | ||
updateInputWithTranscript(""); | ||
resetTranscript(); | ||
}} | ||
className="absolute right-8 h-4 w-4 top-1/2 transform -translate-y-2 text-gray-500 dark:text-gray-400 cursor-pointer hover:scale-125" | ||
/> | ||
<Textarea | ||
value={input} | ||
onChange={handleInputChange} | ||
className="pr-12 resize-none mendable-textarea" | ||
placeholder="Search" | ||
ref={textareaRef} | ||
/> | ||
</div> | ||
|
||
<Button className="h-full"> | ||
{isLoading ? ( | ||
<div className="flex gap-2 items-center"> | ||
<Grid | ||
height={12} | ||
width={12} | ||
radius={5} | ||
ariaLabel="grid-loading" | ||
color="#fff" | ||
visible={true} | ||
/> | ||
{"Loading..."} | ||
</div> | ||
) : ( | ||
<div className="flex flex-col w-16">Send</div> | ||
)} | ||
</Button> | ||
</form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
export function MicIcon( | ||
props: React.JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement> | ||
) { | ||
return ( | ||
<svg | ||
{...props} | ||
xmlns="http://www.w3.org/2000/svg" | ||
width="30" | ||
height="30" | ||
viewBox="0 0 24 24" | ||
fill="none" | ||
stroke="currentColor" | ||
strokeWidth="2" | ||
strokeLinecap="round" | ||
strokeLinejoin="round" | ||
> | ||
<path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" /> | ||
<path d="M19 10v2a7 7 0 0 1-14 0v-2" /> | ||
<line x1="12" x2="12" y1="19" y2="22" /> | ||
</svg> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
export function XIcon( | ||
props: React.JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement> | ||
) { | ||
return ( | ||
<svg | ||
{...props} | ||
xmlns="http://www.w3.org/2000/svg" | ||
width="24" | ||
height="24" | ||
viewBox="0 0 24 24" | ||
fill="none" | ||
stroke="currentColor" | ||
strokeWidth="2" | ||
strokeLinecap="round" | ||
strokeLinejoin="round" | ||
> | ||
<path d="M18 6 6 18" /> | ||
<path d="m6 6 12 12" /> | ||
</svg> | ||
); | ||
} |