diff --git a/web/public/embed.js b/web/public/embed.js index e41405dbf..54aa6a95b 100644 --- a/web/public/embed.js +++ b/web/public/embed.js @@ -38,6 +38,7 @@ height: 43.75rem; max-height: calc(100vh - 6rem); border: none; + border-radius: 1rem; z-index: 2147483640; overflow: hidden; user-select: none; @@ -62,6 +63,7 @@ height: 88%; max-height: calc(100vh - 6rem); border: none; + border-radius: 1rem; z-index: 2147483640; overflow: hidden; user-select: none; diff --git a/web/public/embed.min.js b/web/public/embed.min.js index b1d6f5692..42132e035 100644 --- a/web/public/embed.min.js +++ b/web/public/embed.min.js @@ -1,42 +1,66 @@ -(()=>{let t="difyChatbotConfig",h="dify-chatbot-bubble-button",m="dify-chatbot-bubble-window",y=window[t],a=!1,l=` +(function(){const configKey="difyChatbotConfig";const buttonId="dify-chatbot-bubble-button";const iframeId="dify-chatbot-bubble-window";const config=window[configKey];let isExpanded=false;const svgIcons=` + + + + `;const originalIframeStyleText=` position: absolute; display: flex; flex-direction: column; justify-content: space-between; top: unset; - right: var(--${h}-right, 1rem); /* Align with dify-chatbot-bubble-button. */ - bottom: var(--${h}-bottom, 1rem); /* Align with dify-chatbot-bubble-button. */ + right: var(--${buttonId}-right, 1rem); /* Align with dify-chatbot-bubble-button. */ + bottom: var(--${buttonId}-bottom, 1rem); /* Align with dify-chatbot-bubble-button. */ left: unset; width: 24rem; max-width: calc(100vw - 2rem); height: 43.75rem; max-height: calc(100vh - 6rem); border: none; + border-radius: 1rem; z-index: 2147483640; overflow: hidden; user-select: none; transition-property: width, height; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); transition-duration: 150ms; - `;async function e(){let u=!1;if(y&&y.token){var e=new URLSearchParams({...await(async()=>{var e=y?.inputs||{};let n={};return await Promise.all(Object.entries(e).map(async([e,t])=>{n[e]=await i(t)})),n})(),...await(async()=>{var e=y?.systemVariables||{};let n={};return await Promise.all(Object.entries(e).map(async([e,t])=>{n["sys."+e]=await i(t)})),n})(),...await(async()=>{var e=y?.userVariables||{};let n={};return await Promise.all(Object.entries(e).map(async([e,t])=>{n["user."+e]=await i(t)})),n})()}),n=y.baseUrl||`https://${y.isDev?"dev.":""}udify.app`;let o=new URL(n).origin,t=`${n}/chatbot/${y.token}?`+e;n=s();async function i(e){e=(new TextEncoder).encode(e),e=new Response(new Blob([e]).stream().pipeThrough(new CompressionStream("gzip"))).arrayBuffer(),e=new Uint8Array(await e);return btoa(String.fromCharCode(...e))}function s(){var e=document.createElement("iframe");return e.allow="fullscreen;microphone",e.title="dify chatbot bubble window",e.id=m,e.src=t,e.style.cssText=l,e}function r(){var e,t,n;window.innerWidth<=640||(e=document.getElementById(m),t=document.getElementById(h),e&&t&&(t=t.getBoundingClientRect(),n=window.innerHeight/2,t.top+t.height/2{"className"===e?n.classList.add(...t.split(" ")):"style"===e?"object"==typeof t?Object.assign(n.style,t):n.style.cssText=t:"function"==typeof t?n.addEventListener(e.replace(/^on/,"").toLowerCase(),t):n[e]=t}),n.id=h;var e=document.createElement("style"),e=(document.head.appendChild(e),e.sheet.insertRule(` - #${n.id} { + `;const expandedIframeStyleText=` + position: absolute; + display: flex; + flex-direction: column; + justify-content: space-between; + top: unset; + right: var(--${buttonId}-right, 1rem); /* Align with dify-chatbot-bubble-button. */ + bottom: var(--${buttonId}-bottom, 1rem); /* Align with dify-chatbot-bubble-button. */ + left: unset; + min-width: 24rem; + width: 48%; + max-width: 40rem; /* Match mobile breakpoint*/ + min-height: 43.75rem; + height: 88%; + max-height: calc(100vh - 6rem); + border: none; + border-radius: 1rem; + z-index: 2147483640; + overflow: hidden; + user-select: none; + transition-property: width, height; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + `;async function embedChatbot(){let isDragging=false;if(!config||!config.token){console.error(`${configKey} is empty or token is not provided`);return}async function compressAndEncodeBase64(input){const uint8Array=(new TextEncoder).encode(input);const compressedStream=new Response(new Blob([uint8Array]).stream().pipeThrough(new CompressionStream("gzip"))).arrayBuffer();const compressedUint8Array=new Uint8Array(await compressedStream);return btoa(String.fromCharCode(...compressedUint8Array))}async function getCompressedInputsFromConfig(){const inputs=config?.inputs||{};const compressedInputs={};await Promise.all(Object.entries(inputs).map(async([key,value])=>{compressedInputs[key]=await compressAndEncodeBase64(value)}));return compressedInputs}async function getCompressedSystemVariablesFromConfig(){const systemVariables=config?.systemVariables||{};const compressedSystemVariables={};await Promise.all(Object.entries(systemVariables).map(async([key,value])=>{compressedSystemVariables[`sys.${key}`]=await compressAndEncodeBase64(value)}));return compressedSystemVariables}async function getCompressedUserVariablesFromConfig(){const userVariables=config?.userVariables||{};const compressedUserVariables={};await Promise.all(Object.entries(userVariables).map(async([key,value])=>{compressedUserVariables[`user.${key}`]=await compressAndEncodeBase64(value)}));return compressedUserVariables}const params=new URLSearchParams({...await getCompressedInputsFromConfig(),...await getCompressedSystemVariablesFromConfig(),...await getCompressedUserVariablesFromConfig()});const baseUrl=config.baseUrl||`https://${config.isDev?"dev.":""}udify.app`;const targetOrigin=new URL(baseUrl).origin;const iframeUrl=`${baseUrl}/chatbot/${config.token}?${params}`;const preloadedIframe=createIframe();preloadedIframe.style.display="none";document.body.appendChild(preloadedIframe);if(iframeUrl.length>2048){console.error("The URL is too long, please reduce the number of inputs to prevent the bot from failing to load")}function createIframe(){const iframe=document.createElement("iframe");iframe.allow="fullscreen;microphone";iframe.title="dify chatbot bubble window";iframe.id=iframeId;iframe.src=iframeUrl;iframe.style.cssText=originalIframeStyleText;return iframe}function resetIframePosition(){if(window.innerWidth<=640)return;const targetIframe=document.getElementById(iframeId);const targetButton=document.getElementById(buttonId);if(targetIframe&&targetButton){const buttonRect=targetButton.getBoundingClientRect();const viewportCenterY=window.innerHeight/2;const buttonCenterY=buttonRect.top+buttonRect.height/2;if(buttonCenterY{if(event.origin!==targetOrigin)return;const targetIframe=document.getElementById(iframeId);if(!targetIframe||event.source!==targetIframe.contentWindow)return;if(event.data.type==="dify-chatbot-iframe-ready"){targetIframe.contentWindow?.postMessage({type:"dify-chatbot-config",payload:{isToggledByButton:true,isDraggable:!!config.draggable}},targetOrigin)}if(event.data.type==="dify-chatbot-expand-change"){toggleExpand()}});function createButton(){const containerDiv=document.createElement("div");Object.entries(config.containerProps||{}).forEach(([key,value])=>{if(key==="className"){containerDiv.classList.add(...value.split(" "))}else if(key==="style"){if(typeof value==="object"){Object.assign(containerDiv.style,value)}else{containerDiv.style.cssText=value}}else if(typeof value==="function"){containerDiv.addEventListener(key.replace(/^on/,"").toLowerCase(),value)}else{containerDiv[key]=value}});containerDiv.id=buttonId;const styleSheet=document.createElement("style");document.head.appendChild(styleSheet);styleSheet.sheet.insertRule(` + #${containerDiv.id} { position: fixed; - bottom: var(--${n.id}-bottom, 1rem); - right: var(--${n.id}-right, 1rem); - left: var(--${n.id}-left, unset); - top: var(--${n.id}-top, unset); - width: var(--${n.id}-width, 48px); - height: var(--${n.id}-height, 48px); - border-radius: var(--${n.id}-border-radius, 25px); - background-color: var(--${n.id}-bg-color, #155EEF); - box-shadow: var(--${n.id}-box-shadow, rgba(0, 0, 0, 0.2) 0px 4px 8px 0px); + bottom: var(--${containerDiv.id}-bottom, 1rem); + right: var(--${containerDiv.id}-right, 1rem); + left: var(--${containerDiv.id}-left, unset); + top: var(--${containerDiv.id}-top, unset); + width: var(--${containerDiv.id}-width, 48px); + height: var(--${containerDiv.id}-height, 48px); + border-radius: var(--${containerDiv.id}-border-radius, 25px); + background-color: var(--${containerDiv.id}-bg-color, #155EEF); + box-shadow: var(--${containerDiv.id}-box-shadow, rgba(0, 0, 0, 0.2) 0px 4px 8px 0px); cursor: pointer; z-index: 2147483647; } - `),document.createElement("div"));function t(){var e;u||((e=document.getElementById(m))?(e.style.display="none"===e.style.display?"block":"none","none"===e.style.display?p("open"):p("close"),"none"===e.style.display?document.removeEventListener("keydown",b):document.addEventListener("keydown",b),r()):(n.appendChild(s()),r(),this.title="Exit (ESC)",p("close"),document.addEventListener("keydown",b)))}if(e.style.cssText="position: relative; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; z-index: 2147483647;",e.innerHTML=` - - - - `,n.appendChild(e),document.body.appendChild(n),n.addEventListener("click",t),n.addEventListener("touchend",e=>{e.preventDefault(),t()},{passive:!1}),y.draggable){var a=n;var l=y.dragAxis||"both";let s,r,t,d;function o(e){u=!1,d=("touchstart"===e.type?(s=e.touches[0].clientX-a.offsetLeft,r=e.touches[0].clientY-a.offsetTop,t=e.touches[0].clientX,e.touches[0]):(s=e.clientX-a.offsetLeft,r=e.clientY-a.offsetTop,t=e.clientX,e)).clientY,document.addEventListener("mousemove",i),document.addEventListener("touchmove",i,{passive:!1}),document.addEventListener("mouseup",c),document.addEventListener("touchend",c),e.preventDefault()}function i(n){var o="touchmove"===n.type?n.touches[0]:n,i=o.clientX-t,o=o.clientY-d;if(u=8{u=!1},0),a.style.transition="",a.style.cursor="pointer",document.removeEventListener("mousemove",i),document.removeEventListener("touchmove",i),document.removeEventListener("mouseup",c),document.removeEventListener("touchend",c)}a.addEventListener("mousedown",o),a.addEventListener("touchstart",o)}}n.style.display="none",document.body.appendChild(n),2048{var t,n;e.origin===o&&(t=document.getElementById(m))&&e.source===t.contentWindow&&("dify-chatbot-iframe-ready"===e.data.type&&t.contentWindow?.postMessage({type:"dify-chatbot-config",payload:{isToggledByButton:!0,isDraggable:!!y.draggable}},o),"dify-chatbot-expand-change"===e.data.type)&&(a=!a,n=document.getElementById(m))&&(a?n.style.cssText="\n position: absolute;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n top: unset;\n right: var(--dify-chatbot-bubble-button-right, 1rem); /* Align with dify-chatbot-bubble-button. */\n bottom: var(--dify-chatbot-bubble-button-bottom, 1rem); /* Align with dify-chatbot-bubble-button. */\n left: unset;\n min-width: 24rem;\n width: 48%;\n max-width: 40rem; /* Match mobile breakpoint*/\n min-height: 43.75rem;\n height: 88%;\n max-height: calc(100vh - 6rem);\n border: none;\n z-index: 2147483640;\n overflow: hidden;\n user-select: none;\n transition-property: width, height;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n ":n.style.cssText=l,r())}),document.getElementById(h)||d()}else console.error(t+" is empty or token is not provided")}function p(e="open"){"open"===e?(document.getElementById("openIcon").style.display="block",document.getElementById("closeIcon").style.display="none"):(document.getElementById("openIcon").style.display="none",document.getElementById("closeIcon").style.display="block")}function b(e){"Escape"===e.key&&(e=document.getElementById(m))&&"none"!==e.style.display&&(e.style.display="none",p("open"))}h,h,document.addEventListener("keydown",b),y?.dynamicScript?e():document.body.onload=e})(); \ No newline at end of file + `);const displayDiv=document.createElement("div");displayDiv.style.cssText="position: relative; display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; z-index: 2147483647;";displayDiv.innerHTML=svgIcons;containerDiv.appendChild(displayDiv);document.body.appendChild(containerDiv);containerDiv.addEventListener("click",handleClick);containerDiv.addEventListener("touchend",event=>{event.preventDefault();handleClick()},{passive:false});function handleClick(){if(isDragging)return;const targetIframe=document.getElementById(iframeId);if(!targetIframe){containerDiv.appendChild(createIframe());resetIframePosition();this.title="Exit (ESC)";setSvgIcon("close");document.addEventListener("keydown",handleEscKey);return}targetIframe.style.display=targetIframe.style.display==="none"?"block":"none";targetIframe.style.display==="none"?setSvgIcon("open"):setSvgIcon("close");if(targetIframe.style.display==="none"){document.removeEventListener("keydown",handleEscKey)}else{document.addEventListener("keydown",handleEscKey)}resetIframePosition()}if(config.draggable){enableDragging(containerDiv,config.dragAxis||"both")}}function enableDragging(element,axis){let startX,startY,startClientX,startClientY;element.addEventListener("mousedown",startDragging);element.addEventListener("touchstart",startDragging);function startDragging(e){isDragging=false;if(e.type==="touchstart"){startX=e.touches[0].clientX-element.offsetLeft;startY=e.touches[0].clientY-element.offsetTop;startClientX=e.touches[0].clientX;startClientY=e.touches[0].clientY}else{startX=e.clientX-element.offsetLeft;startY=e.clientY-element.offsetTop;startClientX=e.clientX;startClientY=e.clientY}document.addEventListener("mousemove",drag);document.addEventListener("touchmove",drag,{passive:false});document.addEventListener("mouseup",stopDragging);document.addEventListener("touchend",stopDragging);e.preventDefault()}function drag(e){const touch=e.type==="touchmove"?e.touches[0]:e;const deltaX=touch.clientX-startClientX;const deltaY=touch.clientY-startClientY;if(Math.abs(deltaX)>8||Math.abs(deltaY)>8){isDragging=true}if(!isDragging)return;element.style.transition="none";element.style.cursor="grabbing";const targetIframe=document.getElementById(iframeId);if(targetIframe){targetIframe.style.display="none";setSvgIcon("open")}let newLeft,newBottom;if(e.type==="touchmove"){newLeft=e.touches[0].clientX-startX;newBottom=window.innerHeight-e.touches[0].clientY-startY}else{newLeft=e.clientX-startX;newBottom=window.innerHeight-e.clientY-startY}const elementRect=element.getBoundingClientRect();const maxX=window.innerWidth-elementRect.width;const maxY=window.innerHeight-elementRect.height;if(axis==="x"||axis==="both"){element.style.setProperty(`--${buttonId}-left`,`${Math.max(0,Math.min(newLeft,maxX))}px`)}if(axis==="y"||axis==="both"){element.style.setProperty(`--${buttonId}-bottom`,`${Math.max(0,Math.min(newBottom,maxY))}px`)}}function stopDragging(){setTimeout(()=>{isDragging=false},0);element.style.transition="";element.style.cursor="pointer";document.removeEventListener("mousemove",drag);document.removeEventListener("touchmove",drag);document.removeEventListener("mouseup",stopDragging);document.removeEventListener("touchend",stopDragging)}}if(!document.getElementById(buttonId)){createButton()}}function setSvgIcon(type="open"){if(type==="open"){document.getElementById("openIcon").style.display="block";document.getElementById("closeIcon").style.display="none"}else{document.getElementById("openIcon").style.display="none";document.getElementById("closeIcon").style.display="block"}}function handleEscKey(event){if(event.key==="Escape"){const targetIframe=document.getElementById(iframeId);if(targetIframe&&targetIframe.style.display!=="none"){targetIframe.style.display="none";setSvgIcon("open")}}}document.addEventListener("keydown",handleEscKey);if(config?.dynamicScript){embedChatbot()}else{document.body.onload=embedChatbot}})(); \ No newline at end of file