From 05d797839c38440e11cb0be74c45f97fe27b15ba Mon Sep 17 00:00:00 2001 From: Nuzhy-Deriv Date: Wed, 30 Oct 2024 13:56:14 +0800 Subject: [PATCH 01/19] feat: growthbook hooks added --- .../app/hooks/useGrowthbookGetFeatureValue.js | 35 +++++++++++++++++++ .../app/hooks/useIsGrowthbookLoaded.js | 29 +++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/javascript/app/hooks/useGrowthbookGetFeatureValue.js create mode 100644 src/javascript/app/hooks/useIsGrowthbookLoaded.js diff --git a/src/javascript/app/hooks/useGrowthbookGetFeatureValue.js b/src/javascript/app/hooks/useGrowthbookGetFeatureValue.js new file mode 100644 index 00000000000..c5fa68ce1f4 --- /dev/null +++ b/src/javascript/app/hooks/useGrowthbookGetFeatureValue.js @@ -0,0 +1,35 @@ +import { useEffect, useState } from 'react'; +import { Analytics } from '@deriv-com/analytics'; +import useIsGrowthbookIsLoaded from './useIsGrowthbookLoaded'; + +const useGrowthbookGetFeatureValue = ({ + defaultValue, + featureFlag, +}) => { + const resolvedDefaultValue = defaultValue !== undefined ? defaultValue : false; + const [featureFlagValue, setFeatureFlagValue] = useState( + (Analytics?.getFeatureValue(featureFlag, resolvedDefaultValue) ?? resolvedDefaultValue) + ); + const isGBLoaded = useIsGrowthbookIsLoaded(); + + useEffect(() => { + if (typeof window !== 'undefined') { + window.Analytics = Analytics; + } + + if (isGBLoaded) { + if (Analytics?.getInstances()?.ab) { + const setFeatureValue = () => { + const value = Analytics?.getFeatureValue(featureFlag, resolvedDefaultValue); + setFeatureFlagValue(value); + }; + setFeatureValue(); + Analytics?.getInstances()?.ab?.GrowthBook?.setRenderer(() => { + setFeatureValue(); + }); + } + } + }, [isGBLoaded, resolvedDefaultValue, featureFlag]); + return [featureFlagValue, isGBLoaded]; +}; +export default useGrowthbookGetFeatureValue; diff --git a/src/javascript/app/hooks/useIsGrowthbookLoaded.js b/src/javascript/app/hooks/useIsGrowthbookLoaded.js new file mode 100644 index 00000000000..ae419508bee --- /dev/null +++ b/src/javascript/app/hooks/useIsGrowthbookLoaded.js @@ -0,0 +1,29 @@ +import { useEffect, useState } from 'react'; +import { Analytics } from '@deriv-com/analytics'; + +const useIsGrowthbookIsLoaded = () => { + const [isGBLoaded, setIsGBLoaded] = useState(false); + + useEffect(() => { + let checksCounter = 0; + const analyticsInterval = setInterval(() => { + if (checksCounter > 20) { + clearInterval(analyticsInterval); + return; + } + checksCounter += 1; + if (Analytics?.getInstances()?.ab) { + setIsGBLoaded(true); + clearInterval(analyticsInterval); + } + }, 500); + + return () => { + clearInterval(analyticsInterval); + }; + }, []); + + return isGBLoaded; +}; + +export default useIsGrowthbookIsLoaded; From 7309a0a69d8e490e564b18dfe0fdddcde76212bf Mon Sep 17 00:00:00 2001 From: Nuzhy-Deriv Date: Wed, 30 Oct 2024 15:44:02 +0800 Subject: [PATCH 02/19] chore: open chat funtions --- src/javascript/_common/utility.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/javascript/_common/utility.js b/src/javascript/_common/utility.js index c572a061536..09afda60325 100644 --- a/src/javascript/_common/utility.js +++ b/src/javascript/_common/utility.js @@ -289,6 +289,28 @@ class PromiseClass { const lc_licenseID = 12049137; const lc_clientID = '66aa088aad5a414484c1fd1fa8a5ace7'; +const openChat = () => { + if (window.isFreshChat && window.fcWidget) { + window.fcWidget.open(); + } else { + window.LC_API.open_chat_window(); + } +}; + +const openChatWithParam = () => { + const interval = setInterval(() => { + if (window.isFreshChat && window.fcWidget) { + window.fcWidget.open(); + clearInterval(interval); + } else if (window.LiveChatWidget) { + window.LiveChatWidget.on('ready', () => { + window.LC_API.open_chat_window(); + }); + clearInterval(interval); + } + }, 500); +}; + module.exports = { showLoadingImage, getHighestZIndex, @@ -314,4 +336,6 @@ module.exports = { getHostname, lc_licenseID, lc_clientID, + openChat, + openChatWithParam, }; From 94ced9783cae135626cfcbe16c497f7ad900a1d6 Mon Sep 17 00:00:00 2001 From: Nuzhy-Deriv Date: Wed, 30 Oct 2024 15:44:52 +0800 Subject: [PATCH 03/19] chore: remove unused function --- src/javascript/_common/base/livechat.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/javascript/_common/base/livechat.js b/src/javascript/_common/base/livechat.js index f80078bf6b9..62c90d2cff1 100644 --- a/src/javascript/_common/base/livechat.js +++ b/src/javascript/_common/base/livechat.js @@ -71,21 +71,6 @@ const LiveChat = (() => { } }; - // Fallback LiveChat icon - const livechatFallback = () => { - let livechat_shell; - const livechat_id = 'gtm-deriv-livechat'; - - if (window.LiveChatWidget){ - window.LiveChatWidget.on('ready', () => { - livechat_shell = document.getElementById(livechat_id); - livechat_shell.style.display = 'flex'; - livechat_shell.addEventListener('click', () => window.LC_API.open_chat_window()); - }); - } - - }; - // Delete existing LiveChat instance when there is no chat running const livechatDeletion = () => new Promise ((resolve) => { if (window.LiveChatWidget){ @@ -124,7 +109,6 @@ const LiveChat = (() => { return { initialize, livechatDeletion, - livechatFallback, liveChatInitialization, rerouteGroup, }; From eda6823b5fa6e7a93a07d142f9a06a92ef4800ed Mon Sep 17 00:00:00 2001 From: Nuzhy-Deriv Date: Wed, 30 Oct 2024 15:45:58 +0800 Subject: [PATCH 04/19] fix: freshchat integrated --- src/javascript/app/hooks/use-freshChat.js | 47 ++++++++++++++++++++++ src/javascript/app/pages/livechat.jsx | 49 +++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/javascript/app/hooks/use-freshChat.js create mode 100644 src/javascript/app/pages/livechat.jsx diff --git a/src/javascript/app/hooks/use-freshChat.js b/src/javascript/app/hooks/use-freshChat.js new file mode 100644 index 00000000000..43185b2d593 --- /dev/null +++ b/src/javascript/app/hooks/use-freshChat.js @@ -0,0 +1,47 @@ +import { useEffect, useState } from 'react'; +import { useScript } from 'usehooks-ts'; +import useGrowthbookGetFeatureValue from './useGrowthbookGetFeatureValue'; + +const useFreshChat = (token) => { + const scriptStatus = useScript( + 'https://static.deriv.com/scripts/freshchat.js' + ); + const [isReady, setIsReady] = useState(false); + const [isFreshChatEnabled] = useGrowthbookGetFeatureValue({ + featureFlag: 'enable_freshworks_live_chat', + }); + + useEffect(() => { + const checkFcWidget = (intervalId) => { + if (typeof window !== 'undefined') { + if (window.fcWidget?.isInitialized() === true && !isReady) { + setIsReady(true); + clearInterval(intervalId); + } + } + }; + + const initFreshChat = () => { + if (scriptStatus === 'ready' && window.FreshChat && window.fcSettings) { + window.FreshChat.initialize({ + token, + hideButton: true, + }); + + const intervalId = setInterval(() => checkFcWidget(intervalId), 500); + + return () => clearInterval(intervalId); + } + return null; + }; + + if (isFreshChatEnabled) initFreshChat(); + }, [isFreshChatEnabled, isReady, scriptStatus, token]); + + return { + isReady, + widget: window.fcWidget, + }; +}; + +export default useFreshChat; diff --git a/src/javascript/app/pages/livechat.jsx b/src/javascript/app/pages/livechat.jsx new file mode 100644 index 00000000000..13c7649d3d7 --- /dev/null +++ b/src/javascript/app/pages/livechat.jsx @@ -0,0 +1,49 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import useFreshChat from '../hooks/use-freshChat'; +import useGrowthbookGetFeatureValue from '../hooks/useGrowthbookGetFeatureValue'; + +const LiveChat = () => { + + const loginid = localStorage.getItem('active_loginid'); + const client_info = loginid && JSON.parse(localStorage.getItem('client.accounts') || '{}')[loginid]; + const token = client_info ? client_info.token : null; + + const [isFreshChatEnabled, isGBLoaded] = useGrowthbookGetFeatureValue({ + featureFlag: 'enable_freshworks_live_chat', + }); + console.log('is_freshchat', isFreshChatEnabled); + console.log('isGBLoaded', isGBLoaded); + + const freshChat = useFreshChat(token); + + if (isFreshChatEnabled && freshChat.isReady) { + window.isFreshChat = true; + } else { + window.isFreshChat = false; + } + + return ( + + {!isFreshChatEnabled &&