From 291d6082c91d6666fc536a86e14fc5299bafbb86 Mon Sep 17 00:00:00 2001 From: Antoine Moreaux Date: Tue, 18 Mar 2025 14:23:31 +0100 Subject: [PATCH] refactor(captcha): simplify interval handling in hook (#10974) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close #10708 --------- Co-authored-by: Félix Malfait --- .../CaptchaProviderScriptLoaderEffect.tsx | 26 +++++++++++++++++++ .../MultiWorkspaceDropdownButton.tsx | 19 +++++--------- ...ltiWorkspaceDropdownClickableComponent.tsx | 7 +---- .../MultiWorkspacesDropdownStyles.tsx | 3 --- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/packages/twenty-front/src/modules/captcha/components/CaptchaProviderScriptLoaderEffect.tsx b/packages/twenty-front/src/modules/captcha/components/CaptchaProviderScriptLoaderEffect.tsx index 8611436a8..a2f4db085 100644 --- a/packages/twenty-front/src/modules/captcha/components/CaptchaProviderScriptLoaderEffect.tsx +++ b/packages/twenty-front/src/modules/captcha/components/CaptchaProviderScriptLoaderEffect.tsx @@ -1,16 +1,19 @@ import { useEffect } from 'react'; import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { useRequestFreshCaptchaToken } from '@/captcha/hooks/useRequestFreshCaptchaToken'; import { isCaptchaScriptLoadedState } from '@/captcha/states/isCaptchaScriptLoadedState'; import { getCaptchaUrlByProvider } from '@/captcha/utils/getCaptchaUrlByProvider'; import { captchaState } from '@/client-config/states/captchaState'; import { CaptchaDriverType } from '~/generated/graphql'; +import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; export const CaptchaProviderScriptLoaderEffect = () => { const captcha = useRecoilValue(captchaState); const setIsCaptchaScriptLoaded = useSetRecoilState( isCaptchaScriptLoadedState, ); + const { requestFreshCaptchaToken } = useRequestFreshCaptchaToken(); useEffect(() => { if (!captcha?.provider || !captcha.siteKey) { @@ -43,6 +46,29 @@ export const CaptchaProviderScriptLoaderEffect = () => { document.body.appendChild(scriptElement); } }, [captcha?.provider, captcha?.siteKey, setIsCaptchaScriptLoaded]); + useEffect(() => { + if (isUndefinedOrNull(captcha?.provider)) { + return; + } + + let refreshInterval: NodeJS.Timeout; + + switch (captcha.provider) { + case CaptchaDriverType.GoogleRecaptcha: + // Google reCAPTCHA tokens expire after 120 seconds, refresh at 110 seconds + refreshInterval = setInterval(requestFreshCaptchaToken, 110 * 1000); + break; + case CaptchaDriverType.Turnstile: + // Cloudflare Turnstile tokens expire after 500 seconds, refresh at 480 seconds + refreshInterval = setInterval(requestFreshCaptchaToken, 480 * 1000); + break; + default: + // Note: hCaptcha has a callback system for expiration that we're not implementing now + return; + } + + return () => clearInterval(refreshInterval); + }, [captcha?.provider, requestFreshCaptchaToken]); return <>; }; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/MultiWorkspaceDropdownButton.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/MultiWorkspaceDropdownButton.tsx index 649f4931e..f157df3f2 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/MultiWorkspaceDropdownButton.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/MultiWorkspaceDropdownButton.tsx @@ -1,14 +1,13 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; -import { MULTI_WORKSPACE_DROPDOWN_ID } from '@/ui/navigation/navigation-drawer/constants/MultiWorkspaceDropdownId'; -import { NavigationDrawerHotKeyScope } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerHotKeyScope'; -import { multiWorkspaceDropdownState } from '@/ui/navigation/navigation-drawer/states/multiWorkspaceDropdownState'; -import { useRecoilState } from 'recoil'; -import { useMemo } from 'react'; import { MultiWorkspaceDropdownClickableComponent } from '@/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownClickableComponent'; import { MultiWorkspaceDropdownDefaultComponents } from '@/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownDefaultComponents'; import { MultiWorkspaceDropdownThemesComponents } from '@/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownThemesComponents'; import { MultiWorkspaceDropdownWorkspacesListComponents } from '@/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownWorkspacesListComponents'; -import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; +import { MULTI_WORKSPACE_DROPDOWN_ID } from '@/ui/navigation/navigation-drawer/constants/MultiWorkspaceDropdownId'; +import { multiWorkspaceDropdownState } from '@/ui/navigation/navigation-drawer/states/multiWorkspaceDropdownState'; +import { NavigationDrawerHotKeyScope } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerHotKeyScope'; +import { useMemo } from 'react'; +import { useRecoilState } from 'recoil'; export const MultiWorkspaceDropdownButton = () => { const [multiWorkspaceDropdown, setMultiWorkspaceDropdown] = useRecoilState( @@ -26,8 +25,6 @@ export const MultiWorkspaceDropdownButton = () => { } }, [multiWorkspaceDropdown]); - const { isDropdownOpen } = useDropdown(MULTI_WORKSPACE_DROPDOWN_ID); - return ( { scope: NavigationDrawerHotKeyScope.MultiWorkspaceDropdownButton, }} dropdownOffset={{ y: -35, x: -5 }} - clickableComponent={ - - } + clickableComponent={} dropdownComponents={} onClose={() => { setMultiWorkspaceDropdown('default'); diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownClickableComponent.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownClickableComponent.tsx index 68a0d215c..4bc10b48f 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownClickableComponent.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspaceDropdownClickableComponent.tsx @@ -11,11 +11,7 @@ import { useRecoilValue } from 'recoil'; import { useTheme } from '@emotion/react'; import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded'; -export const MultiWorkspaceDropdownClickableComponent = ({ - isDropdownOpen, -}: { - isDropdownOpen?: boolean; -}) => { +export const MultiWorkspaceDropdownClickableComponent = () => { const currentWorkspace = useRecoilValue(currentWorkspaceState); const theme = useTheme(); @@ -36,7 +32,6 @@ export const MultiWorkspaceDropdownClickableComponent = ({ diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspacesDropdownStyles.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspacesDropdownStyles.tsx index f5266cb92..858b01e9f 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspacesDropdownStyles.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/internal/MultiWorkspacesDropdownStyles.tsx @@ -32,12 +32,9 @@ export const StyledLabel = styled.div` export const StyledIconChevronDown = styled(IconChevronDown)<{ disabled?: boolean; - isDropdownOpen?: boolean; }>` align-items: center; color: ${({ disabled, theme }) => disabled ? theme.font.color.extraLight : theme.font.color.tertiary}; display: flex; - rotate: ${({ isDropdownOpen }) => (isDropdownOpen ? '-180deg' : '0deg')}; - transition: rotate 0.1s ease-in-out; `;