Files
chatwoot/app/javascript/sdk/IFrameHelper.js
Sivin Varghese abf376940d fix: Avoid overflow caused by the empty span element (#9753)
This PR addresses an issue with the `createNotificationBubble` function, which generates an empty `span` element with the class `woot--notification`. This `span` element is currently not utilized anywhere in the code and lacks associated CSS, leading to an overflow issue, specifically in the Firefox browser. It solves the website overflow issue by removing this unused `span` element. This change is unrelated to the unread notification dot, which is working as before.

Fixes https://linear.app/chatwoot/issue/PR-1098/missing-css-for-woot-notification-div
2024-07-10 19:56:46 -07:00

327 lines
9.8 KiB
JavaScript

import Cookies from 'js-cookie';
import {
addClasses,
loadCSS,
removeClasses,
onLocationChangeListener,
} from './DOMHelpers';
import {
body,
widgetHolder,
createBubbleHolder,
createBubbleIcon,
bubbleSVG,
chatBubble,
closeBubble,
bubbleHolder,
onClickChatBubble,
onBubbleClick,
setBubbleText,
addUnreadClass,
removeUnreadClass,
} from './bubbleHelpers';
import { isWidgetColorLighter } from 'shared/helpers/colorHelper';
import { dispatchWindowEvent } from 'shared/helpers/CustomEventHelper';
import { CHATWOOT_ERROR, CHATWOOT_READY } from '../widget/constants/sdkEvents';
import { SET_USER_ERROR } from '../widget/constants/errorTypes';
import { getUserCookieName, setCookieWithDomain } from './cookieHelpers';
import {
getAlertAudio,
initOnEvents,
} from 'shared/helpers/AudioNotificationHelper';
import { isFlatWidgetStyle } from './settingsHelper';
import { popoutChatWindow } from '../widget/helpers/popoutHelper';
import addHours from 'date-fns/addHours';
const updateAuthCookie = (cookieContent, baseDomain = '') =>
setCookieWithDomain('cw_conversation', cookieContent, {
baseDomain,
});
const updateCampaignReadStatus = baseDomain => {
const expireBy = addHours(new Date(), 1);
setCookieWithDomain('cw_snooze_campaigns_till', Number(expireBy), {
expires: expireBy,
baseDomain,
});
};
export const IFrameHelper = {
getUrl({ baseUrl, websiteToken }) {
return `${baseUrl}/widget?website_token=${websiteToken}`;
},
createFrame: ({ baseUrl, websiteToken }) => {
if (IFrameHelper.getAppFrame()) {
return;
}
loadCSS();
const iframe = document.createElement('iframe');
const cwCookie = Cookies.get('cw_conversation');
let widgetUrl = IFrameHelper.getUrl({ baseUrl, websiteToken });
if (cwCookie) {
widgetUrl = `${widgetUrl}&cw_conversation=${cwCookie}`;
}
iframe.src = widgetUrl;
iframe.allow =
'camera;microphone;fullscreen;display-capture;picture-in-picture;clipboard-write;';
iframe.id = 'chatwoot_live_chat_widget';
iframe.style.visibility = 'hidden';
let holderClassName = `woot-widget-holder woot--hide woot-elements--${window.$chatwoot.position}`;
if (window.$chatwoot.hideMessageBubble) {
holderClassName += ` woot-widget--without-bubble`;
}
if (isFlatWidgetStyle(window.$chatwoot.widgetStyle)) {
holderClassName += ` woot-widget-holder--flat`;
}
addClasses(widgetHolder, holderClassName);
widgetHolder.id = 'cw-widget-holder';
widgetHolder.appendChild(iframe);
body.appendChild(widgetHolder);
IFrameHelper.initPostMessageCommunication();
IFrameHelper.initWindowSizeListener();
IFrameHelper.preventDefaultScroll();
},
getAppFrame: () => document.getElementById('chatwoot_live_chat_widget'),
getBubbleHolder: () => document.getElementsByClassName('woot--bubble-holder'),
sendMessage: (key, value) => {
const element = IFrameHelper.getAppFrame();
element.contentWindow.postMessage(
`chatwoot-widget:${JSON.stringify({ event: key, ...value })}`,
'*'
);
},
initPostMessageCommunication: () => {
window.onmessage = e => {
if (
typeof e.data !== 'string' ||
e.data.indexOf('chatwoot-widget:') !== 0
) {
return;
}
const message = JSON.parse(e.data.replace('chatwoot-widget:', ''));
if (typeof IFrameHelper.events[message.event] === 'function') {
IFrameHelper.events[message.event](message);
}
};
},
initWindowSizeListener: () => {
window.addEventListener('resize', () => IFrameHelper.toggleCloseButton());
},
preventDefaultScroll: () => {
widgetHolder.addEventListener('wheel', event => {
const deltaY = event.deltaY;
const contentHeight = widgetHolder.scrollHeight;
const visibleHeight = widgetHolder.offsetHeight;
const scrollTop = widgetHolder.scrollTop;
if (
(scrollTop === 0 && deltaY < 0) ||
(visibleHeight + scrollTop === contentHeight && deltaY > 0)
) {
event.preventDefault();
}
});
},
setFrameHeightToFitContent: (extraHeight, isFixedHeight) => {
const iframe = IFrameHelper.getAppFrame();
const updatedIframeHeight = isFixedHeight ? `${extraHeight}px` : '100%';
if (iframe)
iframe.setAttribute('style', `height: ${updatedIframeHeight} !important`);
},
setupAudioListeners: () => {
const { baseUrl = '' } = window.$chatwoot;
getAlertAudio(baseUrl, { type: 'widget', alertTone: 'ding' }).then(() =>
initOnEvents.forEach(event => {
document.removeEventListener(
event,
IFrameHelper.setupAudioListeners,
false
);
})
);
},
events: {
loaded: message => {
updateAuthCookie(message.config.authToken, window.$chatwoot.baseDomain);
window.$chatwoot.hasLoaded = true;
const campaignsSnoozedTill = Cookies.get('cw_snooze_campaigns_till');
IFrameHelper.sendMessage('config-set', {
locale: window.$chatwoot.locale,
position: window.$chatwoot.position,
hideMessageBubble: window.$chatwoot.hideMessageBubble,
showPopoutButton: window.$chatwoot.showPopoutButton,
widgetStyle: window.$chatwoot.widgetStyle,
darkMode: window.$chatwoot.darkMode,
showUnreadMessagesDialog: window.$chatwoot.showUnreadMessagesDialog,
campaignsSnoozedTill,
});
IFrameHelper.onLoad({
widgetColor: message.config.channelConfig.widgetColor,
});
IFrameHelper.toggleCloseButton();
if (window.$chatwoot.user) {
IFrameHelper.sendMessage('set-user', window.$chatwoot.user);
}
window.playAudioAlert = () => {};
initOnEvents.forEach(e => {
document.addEventListener(e, IFrameHelper.setupAudioListeners, false);
});
if (!window.$chatwoot.resetTriggered) {
dispatchWindowEvent({ eventName: CHATWOOT_READY });
}
},
error: ({ errorType, data }) => {
dispatchWindowEvent({ eventName: CHATWOOT_ERROR, data: data });
if (errorType === SET_USER_ERROR) {
Cookies.remove(getUserCookieName());
}
},
onEvent({ eventIdentifier: eventName, data }) {
dispatchWindowEvent({ eventName, data });
},
setBubbleLabel(message) {
setBubbleText(window.$chatwoot.launcherTitle || message.label);
},
setAuthCookie({ data: { widgetAuthToken } }) {
updateAuthCookie(widgetAuthToken, window.$chatwoot.baseDomain);
},
setCampaignReadOn() {
updateCampaignReadStatus(window.$chatwoot.baseDomain);
},
toggleBubble: state => {
let bubbleState = {};
if (state === 'open') {
bubbleState.toggleValue = true;
} else if (state === 'close') {
bubbleState.toggleValue = false;
}
onBubbleClick(bubbleState);
},
popoutChatWindow: ({ baseUrl, websiteToken, locale }) => {
const cwCookie = Cookies.get('cw_conversation');
window.$chatwoot.toggle('close');
popoutChatWindow(baseUrl, websiteToken, locale, cwCookie);
},
closeWindow: () => {
onBubbleClick({ toggleValue: false });
removeUnreadClass();
},
onBubbleToggle: isOpen => {
IFrameHelper.sendMessage('toggle-open', { isOpen });
if (isOpen) {
IFrameHelper.pushEvent('webwidget.triggered');
}
},
onLocationChange: ({ referrerURL, referrerHost }) => {
IFrameHelper.sendMessage('change-url', {
referrerURL,
referrerHost,
});
},
updateIframeHeight: message => {
const { extraHeight = 0, isFixedHeight } = message;
IFrameHelper.setFrameHeightToFitContent(extraHeight, isFixedHeight);
},
setUnreadMode: () => {
addUnreadClass();
onBubbleClick({ toggleValue: true });
},
resetUnreadMode: () => removeUnreadClass(),
handleNotificationDot: event => {
if (window.$chatwoot.hideMessageBubble) {
return;
}
const bubbleElement = document.querySelector('.woot-widget-bubble');
if (
event.unreadMessageCount > 0 &&
!bubbleElement.classList.contains('unread-notification')
) {
addClasses(bubbleElement, 'unread-notification');
} else if (event.unreadMessageCount === 0) {
removeClasses(bubbleElement, 'unread-notification');
}
},
closeChat: () => {
onBubbleClick({ toggleValue: false });
},
playAudio: () => {
window.playAudioAlert();
},
},
pushEvent: eventName => {
IFrameHelper.sendMessage('push-event', { eventName });
},
onLoad: ({ widgetColor }) => {
const iframe = IFrameHelper.getAppFrame();
iframe.style.visibility = '';
iframe.setAttribute('id', `chatwoot_live_chat_widget`);
if (IFrameHelper.getBubbleHolder().length) {
return;
}
createBubbleHolder(window.$chatwoot.hideMessageBubble);
onLocationChangeListener();
let className = 'woot-widget-bubble';
let closeBtnClassName = `woot-elements--${window.$chatwoot.position} woot-widget-bubble woot--close woot--hide`;
if (isFlatWidgetStyle(window.$chatwoot.widgetStyle)) {
className += ' woot-widget-bubble--flat';
closeBtnClassName += ' woot-widget-bubble--flat';
}
if (isWidgetColorLighter(widgetColor)) {
className += ' woot-widget-bubble-color--lighter';
closeBtnClassName += ' woot-widget-bubble-color--lighter';
}
const chatIcon = createBubbleIcon({
className,
path: bubbleSVG,
target: chatBubble,
});
addClasses(closeBubble, closeBtnClassName);
chatIcon.style.background = widgetColor;
closeBubble.style.background = widgetColor;
bubbleHolder.appendChild(chatIcon);
bubbleHolder.appendChild(closeBubble);
onClickChatBubble();
},
toggleCloseButton: () => {
let isMobile = false;
if (window.matchMedia('(max-width: 668px)').matches) {
isMobile = true;
}
IFrameHelper.sendMessage('toggle-close-button', { isMobile });
},
};