feat: 增加移动端检测功能并优化widget参数传递 & v0.9.69

This commit is contained in:
haorwen
2026-03-17 00:05:34 +08:00
committed by cnb
parent 11e5c982ed
commit 3310a0abdb
5 changed files with 18 additions and 8 deletions
+1 -1
View File
@@ -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",
+7 -2
View File
@@ -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;
+4 -2
View File
@@ -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;
+1 -1
View File
@@ -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` } : {}}
+5 -2
View File
@@ -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}