From 31730cad81de9f657749361224b2bff14e4dfbdf Mon Sep 17 00:00:00 2001 From: n4ze3m Date: Thu, 15 Feb 2024 00:26:13 +0530 Subject: [PATCH] new changes --- src/components/Common/SaveButton.tsx | 2 +- src/components/Option/Layout.tsx | 16 +- .../Option/Playground/PlaygroundEmpty.tsx | 6 +- .../Option/Playground/PlaygroundForm.tsx | 35 +- .../Option/Playground/PlaygroundMessage.tsx | 52 ++- src/components/Option/Settings.tsx | 10 +- src/components/Option/Settings/other.tsx | 37 +- src/css/tailwind.css | 7 +- src/hooks/useMessageOption.tsx | 8 +- src/hooks/useSpeechRecognition.tsx | 176 ++++++++ src/store/option.tsx | 10 +- src/utils/supporetd-languages.ts | 406 ++++++++++++++++++ 12 files changed, 711 insertions(+), 54 deletions(-) create mode 100644 src/hooks/useSpeechRecognition.tsx create mode 100644 src/utils/supporetd-languages.ts diff --git a/src/components/Common/SaveButton.tsx b/src/components/Common/SaveButton.tsx index cf6e950..0aba6d4 100644 --- a/src/components/Common/SaveButton.tsx +++ b/src/components/Common/SaveButton.tsx @@ -26,7 +26,7 @@ export const SaveButton = ({ }, 1000) }} disabled={disabled} - className={`bg-pink-500 text-r mt-4 hover:bg-pink-600 text-white px-4 py-2 rounded-md dark:bg-pink-600 dark:hover:bg-pink-700 ${className}`}> + className={`inline-flex mt-4 items-center rounded-md border border-transparent bg-black px-2 py-2 text-sm font-medium leading-4 text-white shadow-sm dark:bg-white dark:text-gray-800 disabled:opacity-50 ${className}`}> {clickedSave ? textOnSave : text} ) diff --git a/src/components/Option/Layout.tsx b/src/components/Option/Layout.tsx index 7cee36d..37d8934 100644 --- a/src/components/Option/Layout.tsx +++ b/src/components/Option/Layout.tsx @@ -65,7 +65,7 @@ export default function OptionLayout({ queryFn: fetchModels }) - const { selectedModel, setSelectedModel } = useMessageOption() + const { selectedModel, setSelectedModel, clearChat } = useMessageOption() return ( @@ -79,19 +79,29 @@ export default function OptionLayout({
-
+ + {"/"} +
+ option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 || + option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0 + } + onChange={(value) => { + setSpeechToTextLanguage(value) + }} + /> +
+
+ Change Theme
- + Delete Chat History diff --git a/src/css/tailwind.css b/src/css/tailwind.css index 8ace08c..bc57db0 100644 --- a/src/css/tailwind.css +++ b/src/css/tailwind.css @@ -9,4 +9,9 @@ @tailwind base; @tailwind components; -@tailwind utilities; \ No newline at end of file +@tailwind utilities; + +.ant-select-selection-search-input { + border: none !important; + box-shadow: none !important; +} \ No newline at end of file diff --git a/src/hooks/useMessageOption.tsx b/src/hooks/useMessageOption.tsx index b122713..3f496ad 100644 --- a/src/hooks/useMessageOption.tsx +++ b/src/hooks/useMessageOption.tsx @@ -89,7 +89,9 @@ export const useMessageOption = () => { selectedModel, setSelectedModel, chatMode, - setChatMode + setChatMode, + speechToTextLanguage, + setSpeechToTextLanguage } = useStoreMessageOption() const abortControllerRef = React.useRef(null) @@ -301,6 +303,8 @@ export const useMessageOption = () => { selectedModel, setSelectedModel, chatMode, - setChatMode + setChatMode, + speechToTextLanguage, + setSpeechToTextLanguage } } diff --git a/src/hooks/useSpeechRecognition.tsx b/src/hooks/useSpeechRecognition.tsx new file mode 100644 index 0000000..8debe1f --- /dev/null +++ b/src/hooks/useSpeechRecognition.tsx @@ -0,0 +1,176 @@ +import { useRef, useEffect, useState, useCallback } from "react"; + +type SpeechRecognitionEvent = { + results: SpeechRecognitionResultList; + resultIndex: number; +}; + +declare global { + interface SpeechRecognitionErrorEvent extends Event { + error: string; + } + interface Window { + SpeechRecognition: any; + webkitSpeechRecognition: any; + } +} + + + + +type SpeechRecognition = { + lang: string; + interimResults: boolean; + continuous: boolean; + maxAlternatives: number; + grammars: any; + onresult: (event: SpeechRecognitionEvent) => void; + onerror: (event: Event) => void; + onend: () => void; + start: () => void; + stop: () => void; +}; + +type SpeechRecognitionProps = { + onEnd?: () => void; + onResult?: (transcript: string) => void; + onError?: (event: Event) => void; +}; + +type ListenArgs = { + lang?: string; + interimResults?: boolean; + continuous?: boolean; + maxAlternatives?: number; + grammars?: any; +}; + +type SpeechRecognitionHook = { + start: (args?: ListenArgs) => void; + isListening: boolean; + stop: () => void; + supported: boolean; + transcript: string; +}; + +const useEventCallback = any>( + fn: T, + dependencies: any[] +) => { + const ref = useRef(); + + useEffect(() => { + ref.current = fn; + }, [fn, ...dependencies]); + + return useCallback( + (...args: Parameters) => { + const fn = ref.current; + return fn!(...args); + }, + [ref] + ); +}; + +export const useSpeechRecognition = ( + props: SpeechRecognitionProps = {} +): SpeechRecognitionHook => { + const { onEnd = () => {}, onResult = () => {}, onError = () => {} } = props; + const recognition = useRef(null); + const [listening, setListening] = useState(false); + const [supported, setSupported] = useState(false); + const [liveTranscript, setLiveTranscript] = useState(""); + + useEffect(() => { + if (typeof window === "undefined") return; + window.SpeechRecognition = + window.SpeechRecognition || window.webkitSpeechRecognition; + console.log("window.SpeechRecognition", window.SpeechRecognition); + if (window.SpeechRecognition) { + setSupported(true); + recognition.current = new window.SpeechRecognition(); + } + }, []); + + const processResult = (event: SpeechRecognitionEvent) => { + const transcript = Array.from(event.results) + .map((result) => result[0]) + .map((result) => result.transcript) + .join(""); + + onResult(transcript); + }; + + const handleError = (event: Event) => { + if ((event as SpeechRecognitionErrorEvent).error === "not-allowed") { + if (recognition.current) { + recognition.current.onend = null; + } + setListening(false); + } + onError(event); + }; + + const listen = useEventCallback( + (args: ListenArgs = {}) => { + if (listening || !supported) return; + const { + lang = "", + interimResults = true, + continuous = false, + maxAlternatives = 1, + grammars, + } = args; + setListening(true); + setLiveTranscript(""); + if (recognition.current) { + recognition.current.lang = lang; + recognition.current.interimResults = interimResults; + recognition.current.onresult = (event) => { + processResult(event); + const transcript = Array.from(event.results) + .map((result) => result[0]) + .map((result) => result.transcript) + .join(""); + setLiveTranscript(transcript); + }; + recognition.current.onerror = handleError; + recognition.current.continuous = continuous; + recognition.current.maxAlternatives = maxAlternatives; + + if (grammars) { + recognition.current.grammars = grammars; + } + recognition.current.onend = () => { + if (recognition.current) { + recognition.current.start(); + } + }; + if (recognition.current) { + recognition.current.start(); + } + } + }, + [listening, supported, recognition] + ); + + const stop = useEventCallback(() => { + if (!listening || !supported) return; + if (recognition.current) { + recognition.current.onresult = null; + recognition.current.onend = null; + recognition.current.onerror = null; + setListening(false); + recognition.current.stop(); + } + onEnd(); + }, [listening, supported, recognition, onEnd]); + + return { + start: listen, + isListening: listening, + stop, + supported, + transcript: liveTranscript, + }; +}; \ No newline at end of file diff --git a/src/store/option.tsx b/src/store/option.tsx index 4e67ce6..7ad5d2a 100644 --- a/src/store/option.tsx +++ b/src/store/option.tsx @@ -10,7 +10,7 @@ export type Message = { export type ChatHistory = { role: "user" | "assistant" | "system" - content: string, + content: string image?: string }[] @@ -35,6 +35,8 @@ type State = { setChatMode: (chatMode: "normal" | "rag") => void isEmbedding: boolean setIsEmbedding: (isEmbedding: boolean) => void + speechToTextLanguage: string + setSpeechToTextLanguage: (language: string) => void } export const useStoreMessageOption = create((set) => ({ @@ -52,11 +54,13 @@ export const useStoreMessageOption = create((set) => ({ setIsLoading: (isLoading) => set({ isLoading }), isProcessing: false, setIsProcessing: (isProcessing) => set({ isProcessing }), - defaultSpeechToTextLanguage: "en-US", + speechToTextLanguage: "en-US", + setSpeechToTextLanguage: (language) => + set({ speechToTextLanguage: language }), selectedModel: null, setSelectedModel: (selectedModel) => set({ selectedModel }), chatMode: "normal", setChatMode: (chatMode) => set({ chatMode }), isEmbedding: false, - setIsEmbedding: (isEmbedding) => set({ isEmbedding }), + setIsEmbedding: (isEmbedding) => set({ isEmbedding }) })) diff --git a/src/utils/supporetd-languages.ts b/src/utils/supporetd-languages.ts new file mode 100644 index 0000000..968ceb8 --- /dev/null +++ b/src/utils/supporetd-languages.ts @@ -0,0 +1,406 @@ +export const SUPPORTED_LANGUAGES = [ + { + label: "Afrikaans ", + value: "af-ZA" + }, + { + label: "አማርኛ", + value: "am-ET" + }, + { + label: "Azərbaycanca", + value: "az-AZ" + }, + { + label: "বাংলা", + value: "bn-BD" + }, + { + label: "বাংলাদেশ", + value: "bn-IN" + }, + { + label: "Bahasa Indonesia", + value: "id-ID" + }, + { + label: "Bahasa Melayu", + value: "ms-MY" + }, + { + label: "Català", + value: "ca-ES" + }, + { + label: "Čeština", + value: "cs-CZ" + }, + { + label: "Dansk", + value: "da-DK" + }, + { + label: "Deutsch", + value: "de-DE" + }, + { + label: "English (Australia)", + value: "en-AU" + }, + { + label: "English (Canada)", + value: "en-CA" + }, + { + label: "English (India)", + value: "en-IN" + }, + { + label: "English (Kenya)", + value: "en-KE" + }, + { + label: "English (Tanzania)", + value: "en-TZ" + }, + { + label: "English (Ghana)", + value: "en-GH" + }, + { + label: "English (New Zealand)", + value: "en-NZ" + }, + { + label: "English (Nigeria)", + value: "en-NG" + }, + { + label: "English (South Africa)", + value: "en-ZA" + }, + { + label: "English (Philippines)", + value: "en-PH" + }, + { + label: "English (United Kingdom)", + value: "en-GB" + }, + { + label: "English (United States)", + value: "en-US" + }, + { + label: "Español (Argentina)", + value: "es-AR" + }, + { + label: "Español (Bolivia)", + value: "es-BO" + }, + { + label: "Español (Chile)", + value: "es-CL" + }, + { + label: "Español (Colombia)", + value: "es-CO" + }, + { + label: "Español (Costa Rica)", + value: "es-CR" + }, + { + label: "Español (Ecuador)", + value: "es-EC" + }, + { + label: "Español (El Salvador)", + value: "es-SV" + }, + { + label: "Español (España)", + value: "es-ES" + }, + { + label: "Español (Estados Unidos)", + value: "es-US" + }, + { + label: "Español (Guatemala)", + value: "es-GT" + }, + { + label: "Español (Honduras)", + value: "es-HN" + }, + { + label: "Español (México)", + value: "es-MX" + }, + { + label: "Español (Nicaragua)", + value: "es-NI" + }, + { + label: "Español (Panamá)", + value: "es-PA" + }, + { + label: "Español (Paraguay)", + value: "es-PY" + }, + { + label: "Español (Perú)", + value: "es-PE" + }, + { + label: "Español (Puerto Rico)", + value: "es-PR" + }, + { + label: "Español (República Dominicana)", + value: "es-DO" + }, + { + label: "Español (Uruguay)", + value: "es-UY" + }, + { + label: "Español (Venezuela)", + value: "es-VE" + }, + { + label: "Euskara", + value: "eu-ES" + }, + { + label: "Filipino", + value: "fil-PH" + }, + { + label: "Français", + value: "fr-FR" + }, + { + label: "Basa Jawa", + value: "jv-ID" + }, + { + label: "Galego", + value: "gl-ES" + }, + { + label: "ગુજરાતી", + value: "gu-IN" + }, + { + label: "Hrvatski", + value: "hr-HR" + }, + { + label: "IsiZulu", + value: "zu-ZA" + }, + { + label: "Íslenska", + value: "is-IS" + }, + { + label: "Italiano (Italia)", + value: "it-IT" + }, + { + label: "Italiano (Svizzera)", + value: "it-CH" + }, + { + label: "ಕನ್ನಡ", + value: "kn-IN" + }, + { + label: "ភាសាខ្មែរ", + value: "km-KH" + }, + { + label: "Latviešu)", + value: "lv-LV" + }, + { + label: "Lietuvių", + value: "lt-LT" + }, + { + label: "മലയാളം", + value: "ml-IN" + }, + { + label: "मराठी ", + value: "mr-IN" + }, + { + label: "Magyar", + value: "hu-HU" + }, + { + label: "ລາວ", + value: "lo-LA" + }, + { + label: "Nederlands", + value: "nl-NL" + }, + { + label: "नेपाली भाषा", + value: "ne-NP" + }, + { + label: "Norsk bokmål", + value: "nb-NO" + }, + { + label: "Polski", + value: "pl-PL" + }, + { + label: "Português (Brasil)", + value: "pt-BR" + }, + { + label: "Português (Portugal)", + value: "pt-PT" + }, + { + label: "Română", + value: "ro-RO" + }, + { + label: "සිංහල", + value: "si-LK" + }, + { + label: "Slovenščina", + value: "sl-SI" + }, + { + label: "Basa Sunda", + value: "su-ID" + }, + { + label: "Slovenčina ", + value: "sk-SK" + }, + { + label: "Suomi", + value: "fi-FI" + }, + { + label: "Svenska", + value: "sv-SE" + }, + { + label: "Kiswahili (Tanzania)", + value: "sw-TZ" + }, + { + label: "Kiswahili (Kenya)", + value: "sw-KE" + }, + { + label: "ქართული ", + value: "ka-GE" + }, + { + label: "Հայերեն", + value: "hy-AM" + }, + { + label: "தமிழ் (இந்தியா)", + value: "ta-IN" + }, + { + label: "தமிழ் (சிங்கப்பூர்)", + value: "ta-SG" + }, + { + label: "தமிழ் (இலங்கை)", + value: "ta-LK" + }, + { + label: "தமிழ் (மலேசியா)", + value: "ta-MY" + }, + { + label: "తెలుగు", + value: "te-IN" + }, + { + label: "Tiếng Việt", + value: "vi-VN" + }, + { + label: "Türkçe", + value: "tr-TR" + }, + { + label: "اُردُو (پاکستان)", + value: "ur-PK" + }, + { + label: "اُردُو (بھارت)", + value: "ur-IN" + }, + { + label: "Ελληνικά ", + value: "el-GR" + }, + { + label: "български", + value: "bg-BG" + }, + { + label: "Русский", + value: "ru-RU" + }, + { + label: "Српски", + value: "sr-RS" + }, + { + label: "Українська", + value: "uk-UA" + }, + { + label: "한국어 ", + value: "ko-KR" + }, + { + label: "中文 (普通话 中国大陆)", + value: "cmn-Hans-CN" + }, + { + label: "中文 (普通话 香港)", + value: "cmn-Hans-HK" + }, + { + label: "中文 (台灣)", + value: "cmn-Hant-TW" + }, + { + label: "粵語 (香港)", + value: "yue-Hant-HK" + }, + { + label: "日本語", + value: "ja-JP" + }, + { + label: "हिन्दी ", + value: "hi-IN" + }, + { + label: "ภาษาไทย", + value: "th-TH" + } +]