import React, { useContext, useMemo, useRef, useState, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
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 Typography from '../../ui/typography';
import { updateViewedNotifications } from '../../../store/actions';
import { getTranslatedUINotifications } from '../../../../shared/notifications';
import { getSortedAnnouncementsToShow } from '../../../selectors';
import {
BUILD_QUOTE_ROUTE,
ADVANCED_ROUTE,
EXPERIMENTAL_ROUTE,
} from '../../../helpers/constants/routes';
import { TYPOGRAPHY } from '../../../helpers/constants/design-system';
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
function getActionFunctionById(id, history) {
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',
});
},
4: () => {
updateViewedNotifications({ 4: true });
history.push(BUILD_QUOTE_ROUTE);
},
5: () => {
updateViewedNotifications({ 5: true });
global.platform.openTab({
url: ZENDESK_URLS.SECRET_RECOVERY_PHRASE,
});
},
8: () => {
updateViewedNotifications({ 8: true });
history.push(ADVANCED_ROUTE);
},
10: () => {
updateViewedNotifications({ 10: true });
history.push(`${ADVANCED_ROUTE}#token-description`);
},
12: () => {
updateViewedNotifications({ 12: true });
history.push(EXPERIMENTAL_ROUTE);
},
13: () => {
updateViewedNotifications({ 13: true });
history.push(`${EXPERIMENTAL_ROUTE}#show-custom-network`);
},
14: () => {
updateViewedNotifications({ 14: true });
history.push(`${ADVANCED_ROUTE}#backup-userdata`);
},
};
return actionFunctions[id];
}
const renderDescription = (description) => {
if (!Array.isArray(description)) {
return (
{description}
);
}
return (
<>
{description.map((piece, index) => {
const isLast = index === description.length - 1;
return (
{piece}
);
})}
>
);
};
const renderFirstNotification = (notification, idRefMap, history, isLast) => {
const { id, date, title, description, image, actionText } = notification;
const actionFunction = getActionFunctionById(id, history);
const imageComponent = image && (
);
const placeImageBelowDescription = image?.placeImageBelowDescription;
return (
{!placeImageBelowDescription && imageComponent}
{title}
{renderDescription(description)}
{date}
{placeImageBelowDescription && imageComponent}
{actionText && (
)}
);
};
const renderSubsequentNotification = (
notification,
idRefMap,
history,
isLast,
) => {
const { id, date, title, description, actionText } = notification;
const actionFunction = getActionFunctionById(id, history);
return (
{title}
{renderDescription(description)}
{date}
{actionText && (
{`${actionText} >`}
)}
);
};
export default function WhatsNewPopup({ onClose }) {
const t = useContext(I18nContext);
const history = useHistory();
const notifications = useSelector(getSortedAnnouncementsToShow);
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 = getTranslatedUINotifications(t, locale)[id];
const isLast = index === notifications.length - 1;
// Display the swaps notification with full image
return index === 0 || id === 1
? renderFirstNotification(notification, idRefMap, history, isLast)
: renderSubsequentNotification(
notification,
idRefMap,
history,
isLast,
);
})}
);
}
WhatsNewPopup.propTypes = {
onClose: PropTypes.func.isRequired,
};