diff --git a/packages/twenty-front/src/modules/support/components/SupportButton.tsx b/packages/twenty-front/src/modules/support/components/SupportButton.tsx index 11ea7684c..9229232b6 100644 --- a/packages/twenty-front/src/modules/support/components/SupportButton.tsx +++ b/packages/twenty-front/src/modules/support/components/SupportButton.tsx @@ -1,105 +1,16 @@ import styled from '@emotion/styled'; -import { isNonEmptyString } from '@sniptt/guards'; -import { useCallback, useEffect, useState } from 'react'; -import { useRecoilValue } from 'recoil'; import { IconHelpCircle } from 'twenty-ui'; -import { currentUserState } from '@/auth/states/currentUserState'; -import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; -import { supportChatState } from '@/client-config/states/supportChatState'; -import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading'; import { SupportButtonSkeletonLoader } from '@/support/components/SupportButtonSkeletonLoader'; +import { useSupportChat } from '@/support/hooks/useSupportChat'; import { Button } from '@/ui/input/button/components/Button'; -import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; -import { User } from '~/generated/graphql'; -import { isDefined } from '~/utils/isDefined'; const StyledButtonContainer = styled.div` display: flex; `; -const insertScript = ({ - src, - innerHTML, - onLoad, -}: { - src?: string; - innerHTML?: string; - onLoad?: (...args: any[]) => void; -}) => { - const script = document.createElement('script'); - if (isNonEmptyString(src)) script.src = src; - if (isNonEmptyString(innerHTML)) script.innerHTML = innerHTML; - if (isDefined(onLoad)) script.onload = onLoad; - document.body.appendChild(script); -}; - export const SupportButton = () => { - const currentUser = useRecoilValue(currentUserState); - const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); - const supportChat = useRecoilValue(supportChatState); - const [isFrontChatLoaded, setIsFrontChatLoaded] = useState(false); - const loading = useIsPrefetchLoading(); - - const configureFront = useCallback( - ( - chatId: string, - currentUser: Pick, - currentWorkspaceMember: Pick, - ) => { - const url = 'https://chat-assets.frontapp.com/v1/chat.bundle.js'; - let script = document.querySelector(`script[src="${url}"]`); - - // This function only gets called when front chat is not loaded - // If the script is already defined, but front chat is not loaded - // then there was an error loading the script; reload the script - if (isDefined(script)) { - script.parentNode?.removeChild(script); - script = null; - } - - insertScript({ - src: url, - onLoad: () => { - window.FrontChat?.('init', { - chatId, - useDefaultLauncher: false, - email: currentUser.email, - name: - currentWorkspaceMember.name.firstName + - ' ' + - currentWorkspaceMember.name.lastName, - userHash: currentUser?.supportUserHash, - }); - setIsFrontChatLoaded(true); - }, - }); - }, - [], - ); - - useEffect(() => { - if ( - supportChat?.supportDriver === 'front' && - isNonEmptyString(supportChat.supportFrontChatId) && - isNonEmptyString(currentUser?.email) && - isDefined(currentWorkspaceMember) && - !isFrontChatLoaded - ) { - configureFront( - supportChat.supportFrontChatId, - currentUser, - currentWorkspaceMember, - ); - } - }, [ - configureFront, - currentUser, - isFrontChatLoaded, - supportChat?.supportDriver, - supportChat.supportFrontChatId, - currentWorkspaceMember, - ]); + const { loading, isFrontChatLoaded } = useSupportChat(); if (loading) { return ; @@ -112,7 +23,6 @@ export const SupportButton = () => { size="small" title="Support" Icon={IconHelpCircle} - onClick={() => window.FrontChat?.('show')} /> ) : null; diff --git a/packages/twenty-front/src/modules/support/hooks/useSupportChat.ts b/packages/twenty-front/src/modules/support/hooks/useSupportChat.ts new file mode 100644 index 000000000..2fe623a69 --- /dev/null +++ b/packages/twenty-front/src/modules/support/hooks/useSupportChat.ts @@ -0,0 +1,95 @@ +import { currentUserState } from '@/auth/states/currentUserState'; +import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; +import { supportChatState } from '@/client-config/states/supportChatState'; +import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading'; +import { isNonEmptyString } from '@sniptt/guards'; +import { useCallback, useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { isDefined } from 'twenty-ui'; +import { User, WorkspaceMember } from '~/generated-metadata/graphql'; + +const insertScript = ({ + src, + innerHTML, + onLoad, +}: { + src?: string; + innerHTML?: string; + onLoad?: (...args: any[]) => void; +}) => { + const script = document.createElement('script'); + if (isNonEmptyString(src)) script.src = src; + if (isNonEmptyString(innerHTML)) script.innerHTML = innerHTML; + if (isDefined(onLoad)) script.onload = onLoad; + document.body.appendChild(script); +}; + +export const useSupportChat = () => { + const currentUser = useRecoilValue(currentUserState); + const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); + const supportChat = useRecoilValue(supportChatState); + const [isFrontChatLoaded, setIsFrontChatLoaded] = useState(false); + const loading = useIsPrefetchLoading(); + + const configureFront = useCallback( + ( + chatId: string, + currentUser: Pick, + currentWorkspaceMember: Pick, + ) => { + const url = 'https://chat-assets.frontapp.com/v1/chat.bundle.js'; + let script = document.querySelector(`script[src="${url}"]`); + + // This function only gets called when front chat is not loaded + // If the script is already defined, but front chat is not loaded + // then there was an error loading the script; reload the script + if (isDefined(script)) { + script.parentNode?.removeChild(script); + script = null; + } + + insertScript({ + src: url, + onLoad: () => { + window.FrontChat?.('init', { + chatId, + useDefaultLauncher: false, + email: currentUser.email, + name: + currentWorkspaceMember.name.firstName + + ' ' + + currentWorkspaceMember.name.lastName, + userHash: currentUser?.supportUserHash, + }); + setIsFrontChatLoaded(true); + }, + }); + }, + [], + ); + + useEffect(() => { + if ( + supportChat?.supportDriver === 'front' && + isNonEmptyString(supportChat.supportFrontChatId) && + isNonEmptyString(currentUser?.email) && + isDefined(currentWorkspaceMember) && + !isFrontChatLoaded + ) { + configureFront( + supportChat.supportFrontChatId, + currentUser, + currentWorkspaceMember, + ); + } + }, [ + configureFront, + currentUser, + isFrontChatLoaded, + supportChat?.supportDriver, + supportChat.supportFrontChatId, + currentWorkspaceMember, + ]); + + return { loading, isFrontChatLoaded }; +}; diff --git a/packages/twenty-front/src/pages/settings/SettingsBilling.tsx b/packages/twenty-front/src/pages/settings/SettingsBilling.tsx index f348e3455..e184ec40c 100644 --- a/packages/twenty-front/src/pages/settings/SettingsBilling.tsx +++ b/packages/twenty-front/src/pages/settings/SettingsBilling.tsx @@ -14,7 +14,6 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { SettingsBillingCoverImage } from '@/billing/components/SettingsBillingCoverImage'; import { useOnboardingStatus } from '@/onboarding/hooks/useOnboardingStatus'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; -import { SupportButton } from '@/support/components/SupportButton'; import { AppPath } from '@/types/AppPath'; import { Info } from '@/ui/display/info/components/Info'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; @@ -37,10 +36,6 @@ const StyledH1Title = styled(H1Title)` margin-bottom: 0; `; -const StyledInvisibleChat = styled.div` - display: none; -`; - type SwitchInfo = { newInterval: SubscriptionInterval; to: string; @@ -217,9 +212,6 @@ export const SettingsBilling = () => { )} - - -