forked from 77media/video-flow
新增 chatbox的新消息提示与徽记
This commit is contained in:
parent
ba897f08c1
commit
324b4cee90
@ -19,6 +19,8 @@ interface SmartChatBoxProps {
|
||||
onClearPreview?: () => void;
|
||||
setIsFocusChatInput?: (v: boolean) => void;
|
||||
aiEditingResult?: any;
|
||||
/** 新消息回调:用于外层处理未展开时的气泡提示 */
|
||||
onNewMessage?: (snippet: string) => void;
|
||||
}
|
||||
|
||||
interface MessageGroup {
|
||||
@ -47,7 +49,8 @@ export default function SmartChatBox({
|
||||
previewVideoId,
|
||||
onClearPreview,
|
||||
setIsFocusChatInput,
|
||||
aiEditingResult
|
||||
aiEditingResult,
|
||||
onNewMessage
|
||||
}: SmartChatBoxProps) {
|
||||
// 消息列表引用
|
||||
const listRef = useRef<HTMLDivElement>(null);
|
||||
@ -103,6 +106,23 @@ export default function SmartChatBox({
|
||||
onMessagesUpdate: handleMessagesUpdate
|
||||
});
|
||||
|
||||
// 监听消息新增,向外层抛出前10个字符的文本片段
|
||||
const prevLenRef = useRef<number>(0);
|
||||
useEffect(() => {
|
||||
const len = messages.length;
|
||||
if (len > prevLenRef.current && len > 0) {
|
||||
const last = messages[len - 1];
|
||||
// 提取第一个文本块
|
||||
const textBlock = last.blocks.find(b => (b as any).type === 'text') as any;
|
||||
const text = textBlock?.text || '';
|
||||
if (text && onNewMessage) {
|
||||
const snippet = text.slice(0, 20);
|
||||
onNewMessage(snippet);
|
||||
}
|
||||
}
|
||||
prevLenRef.current = len;
|
||||
}, [messages, onNewMessage]);
|
||||
|
||||
// 监听智能剪辑结果,自动发送消息到聊天框
|
||||
// useEffect(() => {
|
||||
// if (aiEditingResult && isSmartChatBoxOpen) {
|
||||
|
||||
@ -10,7 +10,7 @@ import { MediaViewer } from "./work-flow/media-viewer";
|
||||
import { ThumbnailGrid } from "./work-flow/thumbnail-grid";
|
||||
import { useWorkflowData } from "./work-flow/use-workflow-data";
|
||||
import { usePlaybackControls } from "./work-flow/use-playback-controls";
|
||||
import { Bot, TestTube } from "lucide-react";
|
||||
import { Bot, TestTube, MessageCircle } from "lucide-react";
|
||||
import { GlassIconButton } from '@/components/ui/glass-icon-button';
|
||||
import { SaveEditUseCase } from "@/app/service/usecase/SaveEditUseCase";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
@ -48,6 +48,8 @@ const WorkFlow = React.memo(function WorkFlow() {
|
||||
const [isEditModalOpen, setIsEditModalOpen] = React.useState(false);
|
||||
const [activeEditTab, setActiveEditTab] = React.useState('1');
|
||||
const [isSmartChatBoxOpen, setIsSmartChatBoxOpen] = React.useState(true);
|
||||
const [chatTip, setChatTip] = React.useState<string | null>(null);
|
||||
const [hasUnread, setHasUnread] = React.useState(false);
|
||||
const [previewVideoUrl, setPreviewVideoUrl] = React.useState<string | null>(null);
|
||||
const [previewVideoId, setPreviewVideoId] = React.useState<string | null>(null);
|
||||
const [isFocusChatInput, setIsFocusChatInput] = React.useState(false);
|
||||
@ -617,15 +619,30 @@ Please process this video editing request.`;
|
||||
|
||||
{/* 智能对话按钮 */}
|
||||
<div
|
||||
className="fixed right-[1rem] bottom-[10rem] z-[49]"
|
||||
className={`fixed right-[1rem] z-[49] ${isMobile ? 'bottom-[2rem]' : 'bottom-[10rem]'}`}
|
||||
>
|
||||
{isMobile ? (
|
||||
<GlassIconButton
|
||||
icon={Bot}
|
||||
size='md'
|
||||
onClick={() => setIsSmartChatBoxOpen(true)}
|
||||
className="backdrop-blur-lg"
|
||||
/>
|
||||
<div className="relative">
|
||||
{(!isSmartChatBoxOpen && chatTip) && (
|
||||
<div className="absolute -top-8 right-0 bg-black/80 text-white text-xs px-2 py-1 rounded-md whitespace-nowrap">
|
||||
{chatTip}
|
||||
</div>
|
||||
)}
|
||||
{/* 红点徽标 */}
|
||||
{(!isSmartChatBoxOpen && hasUnread) && (
|
||||
<span className="absolute -top-1 -right-1 w-3 h-3 bg-red-500 rounded-full border border-white" />
|
||||
)}
|
||||
<GlassIconButton
|
||||
icon={MessageCircle}
|
||||
size='md'
|
||||
onClick={() => {
|
||||
setIsSmartChatBoxOpen(true);
|
||||
setChatTip(null);
|
||||
setHasUnread(false);
|
||||
}}
|
||||
className="backdrop-blur-lg bg-custom-purple border-transparent hover:opacity-90"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<Tooltip title="Open chat" placement="left">
|
||||
<GlassIconButton
|
||||
@ -641,6 +658,7 @@ Please process this video editing request.`;
|
||||
{/* 智能对话弹窗 */}
|
||||
<Drawer
|
||||
width={isMobile ? '100vw' : '25%'}
|
||||
height={isMobile ? 'auto' : ''}
|
||||
placement={isMobile ? 'bottom' : 'right'}
|
||||
closable={false}
|
||||
maskClosable={false}
|
||||
@ -648,9 +666,9 @@ Please process this video editing request.`;
|
||||
getContainer={false}
|
||||
autoFocus={false}
|
||||
mask={false}
|
||||
zIndex={49}
|
||||
zIndex={60}
|
||||
rootClassName="outline-none"
|
||||
className="backdrop-blur-lg bg-black/30 border border-white/20 shadow-xl"
|
||||
className="backdrop-blur-lg bg-black/30 border border-white/20 shadow-xl max-h-[90vh]"
|
||||
style={{
|
||||
backgroundColor: 'transparent',
|
||||
...(isMobile
|
||||
@ -676,6 +694,14 @@ Please process this video editing request.`;
|
||||
previewVideoUrl={previewVideoUrl}
|
||||
previewVideoId={previewVideoId}
|
||||
setIsFocusChatInput={setIsFocusChatInput}
|
||||
onNewMessage={(snippet) => {
|
||||
if (!isSmartChatBoxOpen && snippet) {
|
||||
setChatTip(snippet);
|
||||
setHasUnread(true);
|
||||
// 3秒后自动消失
|
||||
setTimeout(() => setChatTip(null), 3000);
|
||||
}
|
||||
}}
|
||||
onClearPreview={() => {
|
||||
setPreviewVideoUrl(null);
|
||||
setPreviewVideoId(null);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user