From bc8736c08e8e5f68ad4281d15ab240319b0e2ab5 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Wed, 15 May 2024 10:45:03 +0530 Subject: [PATCH] fix: widget does not load when navigating on pages with view transition [CW-3249] (#9443) * feat: add ids to each element * feat: restore elements for apps that use view transitions * fix: remove generator check condition * feat: handle turbolinks * fix: new body handling * chore: undo debug changes --- app/javascript/packs/sdk.js | 25 ++++++++++++++++++++++++- app/javascript/sdk/DOMHelpers.js | 19 +++++++++++++++++++ app/javascript/sdk/IFrameHelper.js | 1 + app/javascript/sdk/bubbleHelpers.js | 1 + 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/app/javascript/packs/sdk.js b/app/javascript/packs/sdk.js index 9bb8314ca..84cf5fe2d 100755 --- a/app/javascript/packs/sdk.js +++ b/app/javascript/packs/sdk.js @@ -10,14 +10,37 @@ import { getUserCookieName, hasUserKeys, } from '../sdk/cookieHelpers'; -import { addClasses, removeClasses } from '../sdk/DOMHelpers'; +import { + addClasses, + removeClasses, + restoreWidgetInDOM, +} from '../sdk/DOMHelpers'; import { setCookieWithDomain } from '../sdk/cookieHelpers'; import { SDK_SET_BUBBLE_VISIBILITY } from 'shared/constants/sharedFrameEvents'; + const runSDK = ({ baseUrl, websiteToken }) => { if (window.$chatwoot) { return; } + if (window.Turbo) { + // if this is a Rails Turbo app + document.addEventListener('turbo:before-render', event => + restoreWidgetInDOM(event.detail.newBody) + ); + } + + if (window.Turbolinks) { + document.addEventListener('turbolinks:before-render', event => { + restoreWidgetInDOM(event.data.newBody); + }); + } + + // if this is an astro app + document.addEventListener('astro:before-swap', event => + restoreWidgetInDOM(event.newDocument.body) + ); + const chatwootSettings = window.chatwootSettings || {}; let locale = chatwootSettings.locale; let baseDomain = chatwootSettings.baseDomain; diff --git a/app/javascript/sdk/DOMHelpers.js b/app/javascript/sdk/DOMHelpers.js index 47a45cc78..f8ba55337 100644 --- a/app/javascript/sdk/DOMHelpers.js +++ b/app/javascript/sdk/DOMHelpers.js @@ -4,9 +4,28 @@ import { IFrameHelper } from './IFrameHelper'; export const loadCSS = () => { const css = document.createElement('style'); css.innerHTML = `${SDK_CSS}`; + css.id = 'cw-widget-styles'; document.body.appendChild(css); }; +// This is a method specific to Turbo +// The body replacing strategy removes Chatwoot styles +// as well as the widget, this help us get it back +export const restoreElement = (id, newBody) => { + const element = document.getElementById(id); + const newElement = newBody.querySelector(`#${id}`); + + if (element && !newElement) { + newBody.appendChild(element); + } +}; + +export const restoreWidgetInDOM = newBody => { + restoreElement('cw-bubble-holder', newBody); + restoreElement('cw-widget-holder', newBody); + restoreElement('cw-widget-styles', newBody); +}; + export const addClasses = (elm, classes) => { elm.classList.add(...classes.split(' ')); }; diff --git a/app/javascript/sdk/IFrameHelper.js b/app/javascript/sdk/IFrameHelper.js index 2166b4304..3687fa311 100644 --- a/app/javascript/sdk/IFrameHelper.js +++ b/app/javascript/sdk/IFrameHelper.js @@ -78,6 +78,7 @@ export const IFrameHelper = { } addClasses(widgetHolder, holderClassName); + widgetHolder.id = 'cw-widget-holder'; widgetHolder.appendChild(iframe); body.appendChild(widgetHolder); IFrameHelper.initPostMessageCommunication(); diff --git a/app/javascript/sdk/bubbleHelpers.js b/app/javascript/sdk/bubbleHelpers.js index 54401a82c..600c1444a 100644 --- a/app/javascript/sdk/bubbleHelpers.js +++ b/app/javascript/sdk/bubbleHelpers.js @@ -61,6 +61,7 @@ export const createBubbleHolder = hideMessageBubble => { addClasses(bubbleHolder, 'woot-hidden'); } addClasses(bubbleHolder, 'woot--bubble-holder'); + bubbleHolder.id = 'cw-bubble-holder'; body.appendChild(bubbleHolder); };