mirror of
https://github.com/Yidadaa/ChatGPT-Next-Web.git
synced 2025-08-30 18:46:58 +08:00
feat: update voice input button
This commit is contained in:
@@ -1477,8 +1477,11 @@ function _Chat() {
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex gap-2 absolute right-[30px] bottom-[32px]">
|
||||
<div className="flex gap-2 absolute left-[30px] bottom-[32px]">
|
||||
<SpeechRecorder textUpdater={setUserInput}></SpeechRecorder>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2 absolute right-[30px] bottom-[32px]">
|
||||
<IconButton
|
||||
icon={<SendWhiteIcon />}
|
||||
text={Locale.Chat.Send}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import VoiceIcon from "@/app/icons/voice.svg";
|
||||
import { getLang, formatLang } from "@/app/locales";
|
||||
type SpeechRecognitionType =
|
||||
| typeof window.SpeechRecognition
|
||||
| typeof window.webkitSpeechRecognition;
|
||||
@@ -22,29 +23,42 @@ export default function SpeechRecorder({
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (!isRecording && speechRecognition) {
|
||||
speechRecognition.continuous = true; // 连续识别
|
||||
speechRecognition.lang = "zh-CN"; // 设置识别的语言为中文
|
||||
speechRecognition.interimResults = true; // 返回临时结果
|
||||
speechRecognition.start();
|
||||
speechRecognition.onresult = function (event: any) {
|
||||
console.log(event);
|
||||
var transcript = event.results[0][0].transcript; // 获取识别结果
|
||||
console.log(transcript);
|
||||
textUpdater(transcript);
|
||||
};
|
||||
setIsRecording(true);
|
||||
} else {
|
||||
speechRecognition.stop();
|
||||
setIsRecording(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isRecording ? "输入中" : "点击说话"}
|
||||
</button>
|
||||
</div>
|
||||
<>
|
||||
{speechRecognition && (
|
||||
<div>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (!isRecording && speechRecognition) {
|
||||
speechRecognition.continuous = true;
|
||||
speechRecognition.lang = formatLang(getLang());
|
||||
console.log(speechRecognition.lang);
|
||||
speechRecognition.interimResults = true;
|
||||
speechRecognition.start();
|
||||
speechRecognition.onresult = function (event: any) {
|
||||
console.log(event);
|
||||
var transcript = event.results[0][0].transcript;
|
||||
console.log(transcript);
|
||||
textUpdater(transcript);
|
||||
};
|
||||
setIsRecording(true);
|
||||
} else {
|
||||
speechRecognition.stop();
|
||||
setIsRecording(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isRecording ? (
|
||||
<button className="p-2 rounded-full bg-blue-500 hover:bg-blue-600 ring-4 ring-blue-200 transition animate-pulse">
|
||||
<VoiceIcon fill={"white"} />
|
||||
</button>
|
||||
) : (
|
||||
<button className="p-2 rounded-full bg-zinc-100 hover:bg-zinc-200 transition">
|
||||
<VoiceIcon fill={"#8282A5"} />
|
||||
</button>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
11
app/icons/voice.svg
Normal file
11
app/icons/voice.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M5.9375 5.3125C5.9375 3.06884 7.75634 1.25 10 1.25C12.2437 1.25 14.0625 3.06884 14.0625 5.3125V8.75C14.0625 10.9937 12.2437 12.8125 10 12.8125C7.75634 12.8125 5.9375 10.9937 5.9375 8.75V5.3125Z"
|
||||
fill="auto" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M3.35938 7.8125C3.79085 7.8125 4.14062 8.16228 4.14062 8.59375V8.75C4.14062 11.986 6.76396 14.6094 10 14.6094C13.236 14.6094 15.8594 11.986 15.8594 8.75V8.59375C15.8594 8.16228 16.2092 7.8125 16.6406 7.8125C17.0721 7.8125 17.4219 8.16228 17.4219 8.59375V8.75C17.4219 12.849 14.099 16.1719 10 16.1719C5.90101 16.1719 2.57812 12.849 2.57812 8.75V8.59375C2.57812 8.16228 2.9279 7.8125 3.35938 7.8125Z"
|
||||
fill="auto" />
|
||||
<path
|
||||
d="M9.21875 15.4688C9.21875 15.0373 9.56853 14.6875 10 14.6875C10.4315 14.6875 10.7812 15.0373 10.7812 15.4688V17.9688C10.7812 18.4002 10.4315 18.75 10 18.75C9.56853 18.75 9.21875 18.4002 9.21875 17.9688V15.4688Z"
|
||||
fill="auto" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@@ -70,6 +70,28 @@ export const ALL_LANG_OPTIONS: Record<Lang, string> = {
|
||||
sk: "Slovensky",
|
||||
};
|
||||
|
||||
const LANG_CODE_MAPPING = {
|
||||
cn: "zh-CN",
|
||||
en: "en-US",
|
||||
tw: "zh-TW",
|
||||
pt: "pt-BR",
|
||||
jp: "ja-JP",
|
||||
ko: "ko-KR",
|
||||
id: "id-ID",
|
||||
fr: "fr-FR",
|
||||
es: "es-ES",
|
||||
it: "it-IT",
|
||||
tr: "tr-TR",
|
||||
de: "de-DE",
|
||||
vi: "vi-VN",
|
||||
ru: "ru-RU",
|
||||
cs: "cs-CZ",
|
||||
no: "nb-NO",
|
||||
ar: "ar-SA",
|
||||
bn: "bn-BD",
|
||||
sk: "sk-SK",
|
||||
};
|
||||
|
||||
const LANG_KEY = "lang";
|
||||
const DEFAULT_LANG = "en";
|
||||
|
||||
@@ -81,6 +103,13 @@ merge(fallbackLang, targetLang);
|
||||
|
||||
export default fallbackLang as LocaleType;
|
||||
|
||||
export const formatLang = (languageCode: string) => {
|
||||
return (
|
||||
LANG_CODE_MAPPING[languageCode as keyof typeof LANG_CODE_MAPPING] ||
|
||||
languageCode
|
||||
);
|
||||
};
|
||||
|
||||
function getItem(key: string) {
|
||||
try {
|
||||
return localStorage.getItem(key);
|
||||
|
Reference in New Issue
Block a user