This commit is contained in:
Hk-Gosuto
2024-03-24 11:42:06 +08:00
parent 428bf81801
commit a18cb2c525
12 changed files with 112 additions and 18 deletions

View File

@@ -65,6 +65,16 @@
align-items: center;
}
.icon-button-loading-icon {
width: 40px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
fill: white;
stroke: white;
}
@media only screen and (max-width: 600px) {
.icon-button {
padding: 16px;

View File

@@ -4,6 +4,8 @@ import styles from "./button.module.scss";
export type ButtonType = "primary" | "danger" | null;
import LoadingIcon from "../icons/three-dots-white.svg";
export function IconButton(props: {
onClick?: () => void;
icon?: JSX.Element;
@@ -16,6 +18,7 @@ export function IconButton(props: {
disabled?: boolean;
tabIndex?: number;
autoFocus?: boolean;
loding?: boolean;
}) {
return (
<button
@@ -32,7 +35,7 @@ export function IconButton(props: {
tabIndex={props.tabIndex}
autoFocus={props.autoFocus}
>
{props.icon && (
{props.icon && !props.loding && (
<div
className={
styles["icon-button-icon"] +
@@ -43,9 +46,19 @@ export function IconButton(props: {
</div>
)}
{props.text && (
{props.text && !props.loding && (
<div className={styles["icon-button-text"]}>{props.text}</div>
)}
{props.loding ? (
<div
className={
styles["icon-button-loading-icon"] +
` ${props.type === "primary" && "no-dark"}`
}
>
<LoadingIcon />
</div>
) : null}
</button>
);
}

View File

@@ -91,6 +91,7 @@ import {
import { useNavigate } from "react-router-dom";
import {
CHAT_PAGE_SIZE,
DEFAULT_STT_ENGINE,
LAST_INPUT_KEY,
ModelProvider,
Path,
@@ -806,10 +807,10 @@ function _Chat() {
};
const [isListening, setIsListening] = useState(false);
const [isTranscription, setIsTranscription] = useState(false);
const [speechApi, setSpeechApi] = useState<any>(null);
const startListening = async () => {
console.log(speechApi);
if (speechApi) {
await speechApi.start();
setIsListening(true);
@@ -818,6 +819,8 @@ function _Chat() {
const stopListening = async () => {
if (speechApi) {
if (config.sttConfig.engine !== DEFAULT_STT_ENGINE)
setIsTranscription(true);
await speechApi.stop();
setIsListening(false);
}
@@ -826,6 +829,8 @@ function _Chat() {
const onRecognitionEnd = (finalTranscript: string) => {
console.log(finalTranscript);
if (finalTranscript) setUserInput(finalTranscript);
if (config.sttConfig.engine !== DEFAULT_STT_ENGINE)
setIsTranscription(false);
};
const doSubmit = (userInput: string) => {
@@ -899,9 +904,13 @@ function _Chat() {
});
// eslint-disable-next-line react-hooks/exhaustive-deps
setSpeechApi(
new OpenAITranscriptionApi((transcription) =>
onRecognitionEnd(transcription),
),
config.sttConfig.engine === DEFAULT_STT_ENGINE
? new WebTranscriptionApi((transcription) =>
onRecognitionEnd(transcription),
)
: new OpenAITranscriptionApi((transcription) =>
onRecognitionEnd(transcription),
),
);
}, []);
@@ -1695,6 +1704,7 @@ function _Chat() {
onClick={async () =>
isListening ? await stopListening() : await startListening()
}
loding={isTranscription}
/>
) : (
<IconButton

View File

@@ -1,7 +1,8 @@
import { STTConfig } from "../store";
import { STTConfig, STTConfigValidator } from "../store";
import Locale from "../locales";
import { ListItem } from "./ui-lib";
import { ListItem, Select } from "./ui-lib";
import { DEFAULT_STT_ENGINES } from "../constant";
export function STTConfigList(props: {
sttConfig: STTConfig;
@@ -23,6 +24,25 @@ export function STTConfigList(props: {
}
></input>
</ListItem>
<ListItem title={Locale.Settings.STT.Engine.Title}>
<Select
value={props.sttConfig.engine}
onChange={(e) => {
props.updateConfig(
(config) =>
(config.engine = STTConfigValidator.engine(
e.currentTarget.value,
)),
);
}}
>
{DEFAULT_STT_ENGINES.map((v, i) => (
<option value={v} key={i}>
{v}
</option>
))}
</Select>
</ListItem>
</>
);
}