0.4
This commit is contained in:
115
src/pages/chat/QuickReply.tsx
Normal file
115
src/pages/chat/QuickReply.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import { Chip, ScrollShadow } from '@heroui/react';
|
||||
import type { QuickReply as QuickReplyType } from '@mujian/js-sdk/types';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { mjChatCls } from '@/utils/cls';
|
||||
|
||||
export interface QuickReplyProps {
|
||||
quickReplies: Array<QuickReplyType>;
|
||||
onSend: (query: string) => void;
|
||||
}
|
||||
|
||||
export const QuickReply = (props: QuickReplyProps) => {
|
||||
const { quickReplies, onSend } = props;
|
||||
|
||||
const scrollShadowRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const handleWheel = (e: WheelEvent) => {
|
||||
if (Math.abs(e.deltaY) > 0 && scrollShadowRef.current) {
|
||||
e.preventDefault();
|
||||
scrollShadowRef.current.scrollLeft += e.deltaY;
|
||||
}
|
||||
};
|
||||
|
||||
scrollShadowRef?.current?.addEventListener('wheel', handleWheel, {
|
||||
passive: false,
|
||||
});
|
||||
|
||||
return () =>
|
||||
scrollShadowRef?.current?.removeEventListener('wheel', handleWheel);
|
||||
}, []);
|
||||
|
||||
const lastDragTime = useRef(0);
|
||||
|
||||
const onmousedown = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
// 防止文字选择
|
||||
e.preventDefault();
|
||||
|
||||
// 禁用页面文字选择
|
||||
document.body.style.userSelect = 'none';
|
||||
document.body.style.webkitUserSelect = 'none';
|
||||
|
||||
lastDragTime.current = 0;
|
||||
let dragged = false;
|
||||
// biome-ignore lint/suspicious/noExplicitAny: 抄来的代码
|
||||
const mouseMove: EventListener = (e: any) => {
|
||||
dragged = true;
|
||||
if (scrollShadowRef.current) {
|
||||
scrollShadowRef.current.scrollLeft += e.movementX * -2;
|
||||
}
|
||||
};
|
||||
const mouseUp: EventListener = () => {
|
||||
// 恢复文字选择
|
||||
document.body.style.userSelect = '';
|
||||
document.body.style.webkitUserSelect = '';
|
||||
|
||||
document.removeEventListener('mousemove', mouseMove);
|
||||
document.removeEventListener('mouseup', mouseUp);
|
||||
if (dragged) {
|
||||
lastDragTime.current = Date.now();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('mousemove', mouseMove);
|
||||
document.addEventListener('mouseup', mouseUp);
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollShadow
|
||||
ref={scrollShadowRef}
|
||||
hideScrollBar
|
||||
className={mjChatCls(
|
||||
['input-quickreply-container'],
|
||||
'flex w-full overflow-auto gap-2',
|
||||
)}
|
||||
orientation="horizontal"
|
||||
style={{
|
||||
userSelect: 'none',
|
||||
WebkitUserSelect: 'none',
|
||||
MozUserSelect: 'none',
|
||||
msUserSelect: 'none',
|
||||
}}
|
||||
onMouseDown={onmousedown}
|
||||
>
|
||||
{quickReplies.map((qr, index) => (
|
||||
<Chip
|
||||
key={index}
|
||||
className={mjChatCls(
|
||||
['input-quickreply-chip', `input-quickreply-chip-${index + 1}`],
|
||||
'bg-white/15 text-default shrink-0 cursor-pointer',
|
||||
)}
|
||||
classNames={{
|
||||
base: mjChatCls([
|
||||
'input-quickreply-chip-base',
|
||||
`input-quickreply-chip-${index + 1}-base`,
|
||||
]),
|
||||
content: mjChatCls([
|
||||
'input-quickreply-chip-content',
|
||||
`input-quickreply-chip-${index + 1}-content`,
|
||||
]),
|
||||
}}
|
||||
radius="full"
|
||||
variant="light"
|
||||
onClick={() => {
|
||||
const isClick = Date.now() - lastDragTime.current > 50;
|
||||
if (isClick && qr.message) {
|
||||
onSend(qr.message);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{qr.label}
|
||||
</Chip>
|
||||
))}
|
||||
</ScrollShadow>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user