From d422bdf3d3eed0d74ccf5bd1acfcf06c73993418 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 26 Jul 2022 10:58:17 -0500 Subject: [PATCH] Add GdprBanner component, remove useGdpr hook --- app/soapbox/components/gdpr-banner.tsx | 60 ++++++++++++++++++++++++++ app/soapbox/containers/soapbox.tsx | 5 ++- app/soapbox/hooks/index.ts | 1 - app/soapbox/hooks/useGdpr.ts | 48 --------------------- 4 files changed, 63 insertions(+), 51 deletions(-) create mode 100644 app/soapbox/components/gdpr-banner.tsx delete mode 100644 app/soapbox/hooks/useGdpr.ts diff --git a/app/soapbox/components/gdpr-banner.tsx b/app/soapbox/components/gdpr-banner.tsx new file mode 100644 index 000000000..9095d7e03 --- /dev/null +++ b/app/soapbox/components/gdpr-banner.tsx @@ -0,0 +1,60 @@ +import React, { useState } from 'react'; +import { FormattedMessage } from 'react-intl'; + +import { Banner, Button, HStack, Stack, Text } from 'soapbox/components/ui'; +import { useAppSelector, useSoapboxConfig } from 'soapbox/hooks'; + +const acceptedGdpr = !!localStorage.getItem('soapbox:gdpr'); + +/** Displays a cookie consent banner. */ +const GdprBanner: React.FC = () => { + /** Track whether the banner has already been displayed once. */ + const [shown, setShown] = useState(acceptedGdpr); + + const soapbox = useSoapboxConfig(); + const isLoggedIn = useAppSelector(state => !!state.me); + const siteTitle = useAppSelector(state => state.instance.title); + + const handleAccept = () => { + localStorage.setItem('soapbox:gdpr', 'true'); + setShown(true); + }; + + const showBanner = soapbox.gdpr && !isLoggedIn && !shown; + + if (!showBanner) { + return null; + } + + return ( + + + + + + + + + + + + + + + + + + + + ); +}; + +export default GdprBanner; diff --git a/app/soapbox/containers/soapbox.tsx b/app/soapbox/containers/soapbox.tsx index 8be5b2814..603663aa7 100644 --- a/app/soapbox/containers/soapbox.tsx +++ b/app/soapbox/containers/soapbox.tsx @@ -13,6 +13,7 @@ import { fetchMe } from 'soapbox/actions/me'; import { loadSoapboxConfig, getSoapboxConfig } from 'soapbox/actions/soapbox'; import { fetchVerificationConfig } from 'soapbox/actions/verification'; import * as BuildConfig from 'soapbox/build_config'; +import GdprBanner from 'soapbox/components/gdpr-banner'; import Helmet from 'soapbox/components/helmet'; import LoadingScreen from 'soapbox/components/loading-screen'; import AuthLayout from 'soapbox/features/auth_layout'; @@ -34,7 +35,6 @@ import { useSettings, useTheme, useLocale, - useGdpr, } from 'soapbox/hooks'; import MESSAGES from 'soapbox/locales/messages'; import { useCachedLocationHandler } from 'soapbox/utils/redirect'; @@ -78,7 +78,6 @@ const loadInitial = () => { /** Highest level node with the Redux store. */ const SoapboxMount = () => { - useGdpr(); useCachedLocationHandler(); const me = useAppSelector(state => state.me); const instance = useAppSelector(state => state.instance); @@ -178,6 +177,8 @@ const SoapboxMount = () => { {Component => } + + diff --git a/app/soapbox/hooks/index.ts b/app/soapbox/hooks/index.ts index 49f4f6b8b..aad62b1f1 100644 --- a/app/soapbox/hooks/index.ts +++ b/app/soapbox/hooks/index.ts @@ -3,7 +3,6 @@ export { useAppDispatch } from './useAppDispatch'; export { useAppSelector } from './useAppSelector'; export { useDimensions } from './useDimensions'; export { useFeatures } from './useFeatures'; -export { useGdpr } from './useGdpr'; export { useLocale } from './useLocale'; export { useOnScreen } from './useOnScreen'; export { useOwnAccount } from './useOwnAccount'; diff --git a/app/soapbox/hooks/useGdpr.ts b/app/soapbox/hooks/useGdpr.ts deleted file mode 100644 index 49e66bf0c..000000000 --- a/app/soapbox/hooks/useGdpr.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { useEffect, useRef } from 'react'; -import { useIntl, defineMessages } from 'react-intl'; - -import snackbar from 'soapbox/actions/snackbar'; - -import { useAppDispatch } from './useAppDispatch'; -import { useAppSelector } from './useAppSelector'; -import { useSoapboxConfig } from './useSoapboxConfig'; - -const hasGdpr = !!localStorage.getItem('soapbox:gdpr'); - -const messages = defineMessages({ - accept: { id: 'gdpr.accept', defaultMessage: 'Accept' }, - learnMore: { id: 'gdpr.learn_more', defaultMessage: 'Learn more' }, - body: { id: 'gdpr.message', defaultMessage: '{siteTitle} uses session cookies, which are essential to the website\'s functioning.' }, -}); - -/** Displays a GDPR popup unless it has already been accepted. */ -const useGdpr = () => { - const intl = useIntl(); - const dispatch = useAppDispatch(); - - /** Track whether the snackbar has already been displayed once. */ - const triggered = useRef(hasGdpr); - - const soapbox = useSoapboxConfig(); - const isLoggedIn = useAppSelector(state => !!state.me); - const siteTitle = useAppSelector(state => state.instance.title); - - const handleAccept = () => { - localStorage.setItem('soapbox:gdpr', 'true'); - triggered.current = true; - }; - - useEffect(() => { - if (soapbox.gdpr && !isLoggedIn && !triggered.current) { - const message = intl.formatMessage(messages.body, { siteTitle }); - - dispatch(snackbar.show('info', message, { - action: handleAccept, - actionLabel: intl.formatMessage(messages.accept), - dismissAfter: false, - })); - } - }, [soapbox.gdpr, isLoggedIn]); -}; - -export { useGdpr };