From 3310a0abdb8e5b01bd78419d85d919e311ac7665 Mon Sep 17 00:00:00 2001 From: haorwen Date: Tue, 17 Mar 2026 00:05:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E7=AB=AF=E6=A3=80=E6=B5=8B=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96widget=E5=8F=82=E6=95=B0=E4=BC=A0=E9=80=92=20&=20v0.9.?= =?UTF-8?q?69?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- public/widget.js | 9 +++++++-- src/widget/Icon.tsx | 6 ++++-- src/widget/Popup/index.tsx | 2 +- src/widget/WidgetContext.tsx | 7 +++++-- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index ec0a1522..ee13148a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vocechat-web", - "version": "0.9.68", + "version": "0.9.69", "homepage": "https://voce.chat", "dependencies": { "@metamask/onboarding": "^1.0.1", diff --git a/public/widget.js b/public/widget.js index 9618cd63..1e0b58f0 100644 --- a/public/widget.js +++ b/public/widget.js @@ -78,6 +78,8 @@ script.src = `${origin}${manifest.files["widget.js"]}`; script.onload = () => { // 脚本加载完成后,需要手动初始化 React 应用到 shadow DOM + // 检测父窗口是否为移动端 + const isMobile = w.innerWidth < 768; const params = new URLSearchParams({ id, host: hostId, @@ -97,7 +99,8 @@ closeWidth, closeHeight, openWidth, - openHeight + openHeight, + isMobile }); // 将参数传递给 shadow DOM 内的应用 @@ -131,9 +134,11 @@ const wrapper = d.createElement("iframe"); wrapper.id = "VOCECHAT_WIDGET"; Object.assign(wrapper.style, baseStyles); + // 检测父窗口是否为移动端 + const isMobile = w.innerWidth < 768; wrapper.src = `${origin}/widget.html?id=${id}&host=${hostId}&autoReg=${autoReg}&token=${loginToken}&themeColor=${encodeURIComponent( themeColor - )}&from=${encodeURIComponent(location.hostname)}&welcome=${encodeURIComponent(welcome)}&title=${encodeURIComponent(title)}&logo=${encodeURIComponent(logo)}&popupTitle=${encodeURIComponent(popupTitle)}&popupSubtitle=${encodeURIComponent(popupSubtitle)}&popupImage=${encodeURIComponent(popupImage)}&popupClosable=${popupClosable}&showPopup=${showPopup}`; + )}&from=${encodeURIComponent(location.hostname)}&welcome=${encodeURIComponent(welcome)}&title=${encodeURIComponent(title)}&logo=${encodeURIComponent(logo)}&popupTitle=${encodeURIComponent(popupTitle)}&popupSubtitle=${encodeURIComponent(popupSubtitle)}&popupImage=${encodeURIComponent(popupImage)}&popupClosable=${popupClosable}&showPopup=${showPopup}&isMobile=${isMobile}`; wrapper.width = actualCloseWidth; wrapper.height = actualCloseHeight; wrapper.frameborder = 0; diff --git a/src/widget/Icon.tsx b/src/widget/Icon.tsx index a72359a7..2cd5f82c 100644 --- a/src/widget/Icon.tsx +++ b/src/widget/Icon.tsx @@ -10,14 +10,16 @@ type Props = { const Icon = ({ handleClick }: Props) => { const serverLogo = useAppSelector((store) => store.server.logo, shallowEqual); - const { popupTitle, popupSubtitle, popupImage, logo: customLogo, popupClosable, showPopup } = useWidget(); + const { popupTitle, popupSubtitle, popupImage, logo: customLogo, popupClosable, showPopup, embed, isMobile: isMobileFromContext } = useWidget(); const [tooltipVisible, setTooltipVisible] = useState(true); // 优先使用自定义 logo,否则使用服务器 logo const logo = customLogo || serverLogo; // 检测是否是移动端 - const isMobile = typeof window !== 'undefined' && window.innerWidth < 768; + // 在 embed 模式(iframe/shadow DOM)下,使用从父窗口传递的 isMobile 参数 + // 在非 embed 模式下,直接检测当前窗口宽度 + const isMobile = embed ? isMobileFromContext : (typeof window !== 'undefined' && window.innerWidth < 768); // 是否显示 tooltip(桌面端 + 有内容 + 用户未关闭 + showPopup 开关打开) const showTooltip = !isMobile && tooltipVisible && (popupTitle || popupSubtitle) && showPopup; diff --git a/src/widget/Popup/index.tsx b/src/widget/Popup/index.tsx index 66ac6134..0581fc46 100644 --- a/src/widget/Popup/index.tsx +++ b/src/widget/Popup/index.tsx @@ -32,7 +32,7 @@ const Index = ({ handleClose, hostId }: Props) => { className={clsx( "flex flex-col bg-white dark:bg-gray-700 rounded-md overflow-hidden shadow-xl", embed - ? "" + ? "border border-gray-200 dark:border-gray-600" : `w-full h-full md:max-w-lg md:h-[calc(100dvh_-_20px)] m-auto md:my-2 md:shadow-lg rounded-none md:rounded-md` )} style={embed ? { width: `${openWidth}px`, height: `${openHeight}px` } : {}} diff --git a/src/widget/WidgetContext.tsx b/src/widget/WidgetContext.tsx index 9b184e4e..396df239 100644 --- a/src/widget/WidgetContext.tsx +++ b/src/widget/WidgetContext.tsx @@ -32,6 +32,7 @@ const openWidth = parseInt(query.get("openWidth") || "380"); const openHeight = parseInt(query.get("openHeight") || "680"); const closeWidth = parseInt(query.get("closeWidth") || "48"); const closeHeight = parseInt(query.get("closeHeight") || "48"); +const isMobile = query.get("isMobile") === "true"; const WidgetContext = createContext({ id, token, @@ -55,7 +56,8 @@ const WidgetContext = createContext({ openWidth, openHeight, closeWidth, - closeHeight + closeHeight, + isMobile }); function WidgetProvider({ children }: { children: ReactNode }) { @@ -91,7 +93,8 @@ function WidgetProvider({ children }: { children: ReactNode }) { openWidth, openHeight, closeWidth, - closeHeight + closeHeight, + isMobile }} > {children}