From a736948493072ea3c978cc5626d4b19a1dc067e3 Mon Sep 17 00:00:00 2001 From: balibabu Date: Wed, 29 Apr 2026 17:03:33 +0800 Subject: [PATCH] Fix: Clicking the button in the bottom-right corner of the `/chats/widget` page fails to display the dialog box. (#14465) ### What problem does this PR solve? Fix: Clicking the button in the bottom-right corner of the `/chats/widget` page fails to display the dialog box. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) --- .gitignore | 1 + web/src/components/floating-chat-widget.tsx | 50 ++++++++++++------- .../next-message-item/group-button.tsx | 5 +- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 906c13dbfa..f65d204fb2 100644 --- a/.gitignore +++ b/.gitignore @@ -231,3 +231,4 @@ internal/cpp/cmake-build-debug/ # Go server build output bin/* !bin/.gitkeep +.claude/settings.local.json \ No newline at end of file diff --git a/web/src/components/floating-chat-widget.tsx b/web/src/components/floating-chat-widget.tsx index 30f548c8a9..46fb49482a 100644 --- a/web/src/components/floating-chat-widget.tsx +++ b/web/src/components/floating-chat-widget.tsx @@ -4,10 +4,10 @@ import { MessageType, SharedFrom } from '@/constants/chat'; import { useFetchExternalAgentInputs } from '@/hooks/use-agent-request'; import { useFetchExternalChatInfo } from '@/hooks/use-chat-request'; import i18n, { changeLanguageAsync } from '@/locales/config'; -import { useTranslation } from 'react-i18next'; import { useSendNextSharedMessage } from '@/pages/agent/hooks/use-send-shared-message'; import { MessageCircle, Minimize2, Send, X } from 'lucide-react'; import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { useGetSharedChatSearchParams, useSendSharedMessage, @@ -91,6 +91,7 @@ const FloatingChatWidget = () => { oscillator.start(audioContext.currentTime); oscillator.stop(audioContext.currentTime + 0.3); } catch (error) { + console.warn(error); // Silent fail if audio not supported } }, []); @@ -119,6 +120,8 @@ const FloatingChatWidget = () => { oscillator.start(audioContext.currentTime); oscillator.stop(audioContext.currentTime + 0.2); } catch (error) { + console.warn(error); + // Silent fail if audio not supported } }, []); @@ -180,9 +183,11 @@ const FloatingChatWidget = () => { // Master mode - handles everything and creates second iframe dynamically useEffect(() => { if (mode !== 'master') return; - // Create the chat window iframe dynamically when needed - const createChatWindow = () => { - // Check if iframe already exists in parent document + + const isInIframe = window.self !== window.top; + + if (isInIframe) { + // Embedded: tell parent to create chat window iframe window.parent.postMessage( { type: 'CREATE_CHAT_WINDOW', @@ -190,19 +195,29 @@ const FloatingChatWidget = () => { }, '*', ); - }; + } else { + // Standalone: create chat window iframe ourselves + if (!document.getElementById('chat-win')) { + const i = document.createElement('iframe'); + i.id = 'chat-win'; + i.src = window.location.href.replace('mode=master', 'mode=window'); + i.style.cssText = + 'position:fixed;bottom:104px;right:24px;width:380px;height:500px;border:none;background:transparent;z-index:9998;display:none'; + i.frameBorder = '0'; + i.allow = 'microphone;camera'; + document.body.appendChild(i); + } + } - createChatWindow(); - - // Listen for our own toggle events to show/hide the dynamic iframe + // Listen for toggle messages to show/hide the chat window iframe const handleToggle = (e: MessageEvent) => { - if (e.source === window) return; // Ignore our own messages - - const chatWindow = document.getElementById( - 'dynamic-chat-window', - ) as HTMLIFrameElement; - if (chatWindow && e.data.type === 'TOGGLE_CHAT') { - chatWindow.style.display = e.data.isOpen ? 'block' : 'none'; + if (e.data.type === 'TOGGLE_CHAT') { + const chatWindow = document.getElementById( + 'chat-win', + ) as HTMLIFrameElement; + if (chatWindow) { + chatWindow.style.display = e.data.isOpen ? 'block' : 'none'; + } } }; @@ -313,8 +328,9 @@ const FloatingChatWidget = () => { setIsOpen(newIsOpen); if (newIsOpen) playNotificationSound(); - // Tell the parent to show/hide the dynamic iframe - window.parent.postMessage( + // Send toggle message to parent (if embedded) or self (if standalone) + const target = window.self !== window.top ? window.parent : window; + target.postMessage( { type: 'TOGGLE_CHAT', isOpen: newIsOpen, diff --git a/web/src/components/next-message-item/group-button.tsx b/web/src/components/next-message-item/group-button.tsx index 652ef3392c..5b23183116 100644 --- a/web/src/components/next-message-item/group-button.tsx +++ b/web/src/components/next-message-item/group-button.tsx @@ -82,7 +82,10 @@ export const AssistantGroupButton = ({ className="space-x-1" > - + {showLoudspeaker && (