Procházet zdrojové kódy

Fix: Using the Enter key does not send a complete message #6754 (#6755)

### What problem does this PR solve?

Fix: Using the Enter key does not send a complete message #6754

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
tags/v0.18.0
balibabu před 7 měsíci
rodič
revize
aa25d09b0c
Žádný účet není propojen s e-mailovou adresou tvůrce revize

+ 12
- 21
web/src/components/message-input/index.tsx Zobrazit soubor

CloseCircleOutlined, CloseCircleOutlined,
InfoCircleOutlined, InfoCircleOutlined,
LoadingOutlined, LoadingOutlined,
PaperClipOutlined,
SendOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import type { GetProp, UploadFile } from 'antd'; import type { GetProp, UploadFile } from 'antd';
import { import {
UploadProps, UploadProps,
} from 'antd'; } from 'antd';
import get from 'lodash/get'; import get from 'lodash/get';
import { CircleStop } from 'lucide-react';
import { CircleStop, Paperclip, SendHorizontal } from 'lucide-react';
import { import {
ChangeEventHandler, ChangeEventHandler,
memo, memo,


const isUploadingFile = fileList.some((x) => x.status === 'uploading'); const isUploadingFile = fileList.some((x) => x.status === 'uploading');


const handlePressEnter = useCallback(async () => {
if (isUploadingFile) return;
const ids = getFileIds(fileList.filter((x) => isUploadSuccess(x)));

onPressEnter(ids);
setFileList([]);
}, [fileList, onPressEnter, isUploadingFile]);

const handleKeyDown = useCallback( const handleKeyDown = useCallback(
async (event: React.KeyboardEvent<HTMLTextAreaElement>) => { async (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
// check if it was shift + enter // check if it was shift + enter
[sendDisabled, isUploadingFile, sendLoading, handlePressEnter], [sendDisabled, isUploadingFile, sendLoading, handlePressEnter],
); );


const handlePressEnter = useCallback(async () => {
if (isUploadingFile) return;
const ids = getFileIds(fileList.filter((x) => isUploadSuccess(x)));

onPressEnter(ids);
setFileList([]);
}, [fileList, onPressEnter, isUploadingFile]);

const [isComposing, setIsComposing] = useState(false);

const handleCompositionStart = () => setIsComposing(true);
const handleCompositionEnd = () => setIsComposing(false);

const handleRemove = useCallback( const handleRemove = useCallback(
async (file: UploadFile) => { async (file: UploadFile) => {
const ids = get(file, 'response.data', []); const ids = get(file, 'response.data', []);
autoSize={{ minRows: 2, maxRows: 10 }} autoSize={{ minRows: 2, maxRows: 10 }}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
onChange={onInputChange} onChange={onInputChange}
onCompositionStart={handleCompositionStart}
onCompositionEnd={handleCompositionEnd}
/> />
<Divider style={{ margin: '5px 30px 10px 0px' }} /> <Divider style={{ margin: '5px 30px 10px 0px' }} />
<Flex justify="space-between" align="center"> <Flex justify="space-between" align="center">
}} }}
> >
<Button type={'primary'} disabled={disabled}> <Button type={'primary'} disabled={disabled}>
<PaperClipOutlined />
<Paperclip className="size-4" />
</Button> </Button>
</Upload> </Upload>
)} )}
{sendLoading ? ( {sendLoading ? (
<Button onClick={handleStopOutputMessage}> <Button onClick={handleStopOutputMessage}>
<CircleStop />
<CircleStop className="size-5" />
</Button> </Button>
) : ( ) : (
<Button <Button
loading={sendLoading} loading={sendLoading}
disabled={sendDisabled || isUploadingFile || sendLoading} disabled={sendDisabled || isUploadingFile || sendLoading}
> >
<SendOutlined />
<SendHorizontal className="size-5" />
</Button> </Button>
)} )}
</Flex> </Flex>

+ 8
- 11
web/src/pages/chat/markdown-content/index.tsx Zobrazit soubor

import { IReference, IReferenceChunk } from '@/interfaces/database/chat'; import { IReference, IReferenceChunk } from '@/interfaces/database/chat';
import { getExtension } from '@/utils/document-util'; import { getExtension } from '@/utils/document-util';
import { InfoCircleOutlined } from '@ant-design/icons'; import { InfoCircleOutlined } from '@ant-design/icons';
import { Button, Flex, Popover, Space } from 'antd';
import { Button, Flex, Popover } from 'antd';
import DOMPurify from 'dompurify'; import DOMPurify from 'dompurify';
import { useCallback, useEffect, useMemo } from 'react'; import { useCallback, useEffect, useMemo } from 'react';
import Markdown from 'react-markdown'; import Markdown from 'react-markdown';
import { preprocessLaTeX, replaceThinkToSection } from '@/utils/chat'; import { preprocessLaTeX, replaceThinkToSection } from '@/utils/chat';
import { replaceTextByOldReg } from '../utils'; import { replaceTextByOldReg } from '../utils';


import classNames from 'classnames';
import { pipe } from 'lodash/fp'; import { pipe } from 'lodash/fp';
import styles from './index.less'; import styles from './index.less';


const fileExtension = documentId ? getExtension(document?.doc_name) : ''; const fileExtension = documentId ? getExtension(document?.doc_name) : '';
const imageId = chunkItem?.image_id; const imageId = chunkItem?.image_id;
return ( return (
<Flex
key={chunkItem?.id}
gap={10}
className={styles.referencePopoverWrapper}
>
<div key={chunkItem?.id} className="flex gap-2">
{imageId && ( {imageId && (
<Popover <Popover
placement="left" placement="left"
></Image> ></Image>
</Popover> </Popover>
)} )}
<Space direction={'vertical'}>
<div className={'space-y-2 max-w-[40vw]'}>
<div <div
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(chunkItem?.content ?? ''), __html: DOMPurify.sanitize(chunkItem?.content ?? ''),
}} }}
className={styles.chunkContentText}
className={classNames(styles.chunkContentText)}
></div> ></div>
{documentId && ( {documentId && (
<Flex gap={'small'}> <Flex gap={'small'}>
)} )}
<Button <Button
type="link" type="link"
className={styles.documentLink}
className={classNames(styles.documentLink, 'text-wrap')}
onClick={handleDocumentButtonClick( onClick={handleDocumentButtonClick(
documentId, documentId,
chunkItem, chunkItem,
</Button> </Button>
</Flex> </Flex>
)} )}
</Space>
</Flex>
</div>
</div>
); );
}, },
[reference, fileThumbnails, handleDocumentButtonClick], [reference, fileThumbnails, handleDocumentButtonClick],

+ 1
- 1
web/src/pages/chat/utils.ts Zobrazit soubor



// To be compatible with the old index matching mode // To be compatible with the old index matching mode
export const replaceTextByOldReg = (text: string) => { export const replaceTextByOldReg = (text: string) => {
return text.replace(oldReg, function (substring) {
return text?.replace(oldReg, function (substring) {
return `~~${substring.slice(2, -2)}==`; return `~~${substring.slice(2, -2)}==`;
}); });
}; };

Načítá se…
Zrušit
Uložit