瀏覽代碼

feat: After the voice in the new conversation window is played, jump to the tab of the conversation #1877 (#2440)

### What problem does this PR solve?

feat: After the voice in the new conversation window is played, jump to
the tab of the conversation #1877

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
tags/v0.11.0
balibabu 1 年之前
父節點
當前提交
1621313c0f
沒有連結到貢獻者的電子郵件帳戶。

+ 6
- 2
web/src/components/message-item/hooks.ts 查看文件

import { useSetModalState } from '@/hooks/common-hooks'; import { useSetModalState } from '@/hooks/common-hooks';
import { IRemoveMessageById, useSpeechWithSse } from '@/hooks/logic-hooks'; import { IRemoveMessageById, useSpeechWithSse } from '@/hooks/logic-hooks';
import { IFeedbackRequestBody } from '@/interfaces/request/chat'; import { IFeedbackRequestBody } from '@/interfaces/request/chat';
import { ConversationContext } from '@/pages/chat/context';
import { getMessagePureId } from '@/utils/chat'; import { getMessagePureId } from '@/utils/chat';
import { hexStringToUint8Array } from '@/utils/common-util'; import { hexStringToUint8Array } from '@/utils/common-util';
import { SpeechPlayer } from 'openai-speech-stream-player'; import { SpeechPlayer } from 'openai-speech-stream-player';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useContext, useEffect, useRef, useState } from 'react';


export const useSendFeedback = (messageId: string) => { export const useSendFeedback = (messageId: string) => {
const { visible, hideModal, showModal } = useSetModalState(); const { visible, hideModal, showModal } = useSetModalState();
const { read } = useSpeechWithSse(); const { read } = useSpeechWithSse();
const player = useRef<SpeechPlayer>(); const player = useRef<SpeechPlayer>();
const [isPlaying, setIsPlaying] = useState<boolean>(false); const [isPlaying, setIsPlaying] = useState<boolean>(false);
const callback = useContext(ConversationContext);


const initialize = useCallback(async () => { const initialize = useCallback(async () => {
player.current = new SpeechPlayer({ player.current = new SpeechPlayer({
audio: ref.current!, audio: ref.current!,
onPlaying: () => { onPlaying: () => {
setIsPlaying(true); setIsPlaying(true);
callback?.(true);
}, },
onPause: () => { onPause: () => {
setIsPlaying(false); setIsPlaying(false);
callback?.(false);
}, },
onChunkEnd: () => {}, onChunkEnd: () => {},
mimeType: 'audio/mpeg', mimeType: 'audio/mpeg',
}); });
await player.current.init(); await player.current.init();
}, []);
}, [callback]);


const pause = useCallback(() => { const pause = useCallback(() => {
player.current?.pause(); player.current?.pause();

+ 1
- 0
web/src/interfaces/database/chat.ts 查看文件

parameters: Parameter[]; parameters: Parameter[];
prologue: string; prologue: string;
system: string; system: string;
tts?: boolean;
} }


export interface Parameter { export interface Parameter {

+ 32
- 28
web/src/pages/chat/chat-container/index.tsx 查看文件

} from '@/hooks/chat-hooks'; } from '@/hooks/chat-hooks';
import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; import { useFetchUserInfo } from '@/hooks/user-setting-hooks';
import { memo } from 'react'; import { memo } from 'react';
import { ConversationContext } from '../context';
import styles from './index.less'; import styles from './index.less';


const ChatContainer = () => { const ChatContainer = () => {
const { data: conversation } = useFetchNextConversation(); const { data: conversation } = useFetchNextConversation();


const { const {
value,
ref, ref,
loading, loading,
sendLoading, sendLoading,
derivedMessages, derivedMessages,
handleInputChange, handleInputChange,
handlePressEnter, handlePressEnter,
value,
regenerateMessage, regenerateMessage,
removeMessageById, removeMessageById,
redirectToNewConversation,
} = useSendNextMessage(); } = useSendNextMessage();


const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } = const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
<Flex flex={1} vertical className={styles.messageContainer}> <Flex flex={1} vertical className={styles.messageContainer}>
<div> <div>
<Spin spinning={loading}> <Spin spinning={loading}>
{derivedMessages?.map((message, i) => {
return (
<MessageItem
loading={
message.role === MessageType.Assistant &&
sendLoading &&
derivedMessages.length - 1 === i
}
key={message.id}
item={message}
nickname={userInfo.nickname}
avatar={userInfo.avatar}
reference={buildMessageItemReference(
{
message: derivedMessages,
reference: conversation.reference,
},
message,
)}
clickDocumentButton={clickDocumentButton}
index={i}
removeMessageById={removeMessageById}
regenerateMessage={regenerateMessage}
sendLoading={sendLoading}
></MessageItem>
);
})}
<ConversationContext.Provider value={redirectToNewConversation}>
{derivedMessages?.map((message, i) => {
return (
<MessageItem
loading={
message.role === MessageType.Assistant &&
sendLoading &&
derivedMessages.length - 1 === i
}
key={message.id}
item={message}
nickname={userInfo.nickname}
avatar={userInfo.avatar}
reference={buildMessageItemReference(
{
message: derivedMessages,
reference: conversation.reference,
},
message,
)}
clickDocumentButton={clickDocumentButton}
index={i}
removeMessageById={removeMessageById}
regenerateMessage={regenerateMessage}
sendLoading={sendLoading}
></MessageItem>
);
})}
</ConversationContext.Provider>
</Spin> </Spin>
</div> </div>
<div ref={ref} /> <div ref={ref} />

+ 5
- 0
web/src/pages/chat/context.ts 查看文件

import { createContext } from 'react';

export const ConversationContext = createContext<
null | ((isPlaying: boolean) => void)
>(null);

+ 18
- 1
web/src/pages/chat/hooks.ts 查看文件

useCallback, useCallback,
useEffect, useEffect,
useMemo, useMemo,
useRef,
useState, useState,
} from 'react'; } from 'react';
import { useSearchParams } from 'umi'; import { useSearchParams } from 'umi';
removeMessageById, removeMessageById,
removeMessagesAfterCurrentMessage, removeMessagesAfterCurrentMessage,
} = useSelectNextMessages(); } = useSelectNextMessages();
const { data: dialog } = useFetchNextDialog();
const currentConversationIdRef = useRef<string>('');

const redirectToNewConversation = useCallback(
(isPlaying: boolean) => {
if (!conversationId && dialog?.prompt_config?.tts && !isPlaying) {
handleClickConversation(currentConversationIdRef.current);
}
},
[dialog, handleClickConversation, conversationId],
);


const sendMessage = useCallback( const sendMessage = useCallback(
async ({ async ({
if (currentConversationId) { if (currentConversationId) {
console.info('111'); console.info('111');
// new conversation // new conversation
handleClickConversation(currentConversationId);
if (!dialog?.prompt_config?.tts) {
handleClickConversation(currentConversationId);
}
} else { } else {
console.info('222'); console.info('222');
// fetchConversation(conversationId); // fetchConversation(conversationId);
} }
}, },
[ [
dialog,
derivedMessages, derivedMessages,
conversationId, conversationId,
handleClickConversation, handleClickConversation,
const data = await setConversation(message.content); const data = await setConversation(message.content);
if (data.retcode === 0) { if (data.retcode === 0) {
const id = data.data.id; const id = data.data.id;
currentConversationIdRef.current = id;
sendMessage({ sendMessage({
message, message,
currentConversationId: id, currentConversationId: id,
ref, ref,
derivedMessages, derivedMessages,
removeMessageById, removeMessageById,
redirectToNewConversation,
}; };
}; };



Loading…
取消
儲存