Echo 6308fcd9f8 [Glitch] Add more resilience to Emoji IDB upgrades
Port 1dc2abb9f5b430f80e771f214343983919cd543d to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
2026-06-24 17:30:07 +02:00

106 lines
2.6 KiB
TypeScript

import { useState, useEffect } from 'react';
import { defineMessage, useIntl } from 'react-intl';
import type { IntlShape } from 'react-intl';
import { dismissAlert } from 'flavours/glitch/actions/alerts';
import type {
Alert as AlertType,
TranslatableString,
TranslatableValues,
} from 'flavours/glitch/models/alert';
import { useAppSelector, useAppDispatch } from 'flavours/glitch/store';
import { A11yLiveRegion } from './a11y_live_region';
import { Alert } from './alert';
const formatIfNeeded = (
intl: IntlShape,
message: TranslatableString,
values?: TranslatableValues,
) => {
if (typeof message === 'object') {
return intl.formatMessage(message, values);
}
return message;
};
const TimedAlert: React.FC<{
alert: AlertType;
dismissAfter: number;
}> = ({
alert: { key, title, message, values, action, onClick },
dismissAfter,
}) => {
const dispatch = useAppDispatch();
const intl = useIntl();
const [active, setActive] = useState(false);
useEffect(() => {
const setActiveTimeout = setTimeout(() => {
setActive(true);
}, 1);
return () => {
clearTimeout(setActiveTimeout);
};
}, []);
useEffect(() => {
const dismissTimeout = setTimeout(() => {
setActive(false);
// Allow CSS transition to finish before removing from the DOM
setTimeout(() => {
dispatch(dismissAlert({ key }));
}, 500);
}, dismissAfter);
return () => {
clearTimeout(dismissTimeout);
};
}, [dispatch, setActive, key, dismissAfter]);
return (
<Alert
isActive={active}
title={title ? formatIfNeeded(intl, title, values) : undefined}
message={formatIfNeeded(intl, message, values)}
action={action ? formatIfNeeded(intl, action, values) : undefined}
onActionClick={onClick}
/>
);
};
export const AlertsController: React.FC = () => {
const alerts = useAppSelector((state) => state.alerts);
const needsReload = useAppSelector(
(state) => !!state.meta.get('needsReload'),
);
return (
<A11yLiveRegion className='notification-list'>
{alerts.map((alert, idx) => (
<TimedAlert
key={alert.key}
alert={alert}
dismissAfter={5000 + idx * 1000}
/>
))}
{needsReload && <ReloadAlert />}
</A11yLiveRegion>
);
};
const reloadMessage = defineMessage({
id: 'alert.need_reload.message',
defaultMessage:
'Mastodon has been updated. Some things may not work correctly until you reload the page.',
});
const ReloadAlert: React.FC = () => {
const intl = useIntl();
return <Alert isActive message={intl.formatMessage(reloadMessage)} />;
};