From 3733d346d7477c4fe399027dccec0f186cd7283d Mon Sep 17 00:00:00 2001 From: Li Xin Date: Fri, 18 Apr 2025 22:06:51 +0800 Subject: [PATCH] feat: add `Listen to the report` --- .../app/_components/research-report-block.tsx | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/web/src/app/_components/research-report-block.tsx b/web/src/app/_components/research-report-block.tsx index 705f135..7a99a7f 100644 --- a/web/src/app/_components/research-report-block.tsx +++ b/web/src/app/_components/research-report-block.tsx @@ -1,6 +1,15 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: MIT +import { PauseCircleOutlined, SoundOutlined } from "@ant-design/icons"; +import { useCallback, useRef, useState } from "react"; + +import { Button } from "~/components/ui/button"; +import { + Tooltip, + TooltipTrigger, + TooltipContent, +} from "~/components/ui/tooltip"; import { useMessage } from "~/core/store"; import { cn } from "~/lib/utils"; @@ -15,8 +24,48 @@ export function ResearchReportBlock({ messageId: string; }) { const message = useMessage(messageId); + const contentRef = useRef(null); + const [isTTS, setIsTTS] = useState(false); + const handleTTS = useCallback(() => { + if (contentRef.current) { + if (isTTS) { + window.speechSynthesis.cancel(); + setIsTTS(false); + } else { + const text = contentRef.current.textContent; + if (text) { + const utterance = new SpeechSynthesisUtterance(text); + setIsTTS(true); + window.speechSynthesis.speak(utterance); + } + } + } + }, [isTTS]); return ( -
+
+
+ {message?.content && !message.isStreaming && ( + + + + + +

{isTTS ? "Pause" : "Listen to the report"}

+
+
+ )} +
{message?.content} {message?.isStreaming && }