import React, { useContext, useMemo, useRef, useState, useEffect } from 'react'; import { useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { getCurrentLocale } from '../../../ducks/metamask/metamask'; import { I18nContext } from '../../../contexts/i18n'; import { useEqualityCheck } from '../../../hooks/useEqualityCheck'; import Button from '../../ui/button'; import Popover from '../../ui/popover'; import { updateViewedNotifications } from '../../../store/actions'; import { getTranslatedUINoficiations } from '../../../../shared/notifications'; import { getSortedNotificationsToShow } from '../../../selectors'; function getActionFunctionById(id) { const actionFunctions = { 2: () => { global.platform.openTab({ url: 'https://survey.alchemer.com/s3/6173069/MetaMask-Extension-NPS-January-2021', }); }, 3: () => { global.platform.openTab({ url: 'https://community.metamask.io/t/about-the-security-category/72', }); }, }; return actionFunctions[id]; } const renderFirstNotification = (notification, idRefMap) => { const { id, date, title, description, image, actionText } = notification; const actionFunction = getActionFunctionById(id); const imageComponent = image && ( ); const placeImageBelowDescription = image?.placeImageBelowDescription; return (
{!placeImageBelowDescription && imageComponent}
{title}
{description}
{date}
{placeImageBelowDescription && imageComponent} {actionText && ( )}
); }; const renderSubsequentNotification = (notification, idRefMap) => { const { id, date, title, description, actionText } = notification; const actionFunction = getActionFunctionById(id); return (
{title}
{description}
{date}
{actionText && (
{`${actionText} >`}
)}
); }; export default function WhatsNewPopup({ onClose }) { const t = useContext(I18nContext); const notifications = useSelector(getSortedNotificationsToShow); const locale = useSelector(getCurrentLocale); const [seenNotifications, setSeenNotifications] = useState({}); const popoverRef = useRef(); const memoizedNotifications = useEqualityCheck(notifications); const idRefMap = useMemo( () => memoizedNotifications.reduce( (_idRefMap, notification) => ({ ..._idRefMap, [notification.id]: React.createRef(), }), {}, ), [memoizedNotifications], ); useEffect(() => { const observer = new window.IntersectionObserver( (entries, _observer) => { entries.forEach((entry) => { if (entry.isIntersecting) { const [id, ref] = Object.entries(idRefMap).find(([_, _ref]) => _ref.current.isSameNode(entry.target), ); setSeenNotifications((_seenNotifications) => ({ ..._seenNotifications, [id]: true, })); _observer.unobserve(ref.current); } }); }, { root: popoverRef.current, threshold: 1.0, }, ); Object.values(idRefMap).forEach((ref) => { observer.observe(ref.current); }); return () => { observer.disconnect(); }; }, [idRefMap, setSeenNotifications]); return ( { updateViewedNotifications(seenNotifications); onClose(); }} popoverRef={popoverRef} >
{notifications.map(({ id }, index) => { const notification = getTranslatedUINoficiations(t, locale)[id]; return index === 0 ? renderFirstNotification(notification, idRefMap) : renderSubsequentNotification(notification, idRefMap); })}
); } WhatsNewPopup.propTypes = { onClose: PropTypes.func.isRequired, };