catstodon/app/javascript/mastodon/features/ui/components/embed_modal.tsx
2024-09-12 12:54:16 +00:00

116 lines
3.2 KiB
TypeScript

import { useRef, useState, useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { showAlertForError } from 'mastodon/actions/alerts';
import api from 'mastodon/api';
import { Button } from 'mastodon/components/button';
import { CopyPasteText } from 'mastodon/components/copy_paste_text';
import { useAppDispatch } from 'mastodon/store';
interface OEmbedResponse {
html: string;
}
const EmbedModal: React.FC<{
id: string;
onClose: () => void;
}> = ({ id, onClose }) => {
const iframeRef = useRef<HTMLIFrameElement>(null);
const intervalRef = useRef<ReturnType<typeof setInterval>>();
const [oembed, setOembed] = useState<OEmbedResponse | null>(null);
const dispatch = useAppDispatch();
useEffect(() => {
api()
.get(`/api/web/embeds/${id}`)
.then((res) => {
const data = res.data as OEmbedResponse;
setOembed(data);
const iframeDocument = iframeRef.current?.contentWindow?.document;
if (!iframeDocument) {
return '';
}
iframeDocument.open();
iframeDocument.write(data.html);
iframeDocument.close();
iframeDocument.body.style.margin = '0px';
// This is our best chance to ensure the parent iframe has the correct height...
intervalRef.current = setInterval(
() =>
window.requestAnimationFrame(() => {
if (iframeRef.current) {
iframeRef.current.width = `${iframeDocument.body.scrollWidth}px`;
iframeRef.current.height = `${iframeDocument.body.scrollHeight}px`;
}
}),
100,
);
return '';
})
.catch((error: unknown) => {
dispatch(showAlertForError(error));
});
}, [dispatch, id, setOembed]);
useEffect(
() => () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
},
[],
);
return (
<div className='modal-root__modal dialog-modal'>
<div className='dialog-modal__header'>
<Button onClick={onClose}>
<FormattedMessage id='report.close' defaultMessage='Done' />
</Button>
<span className='dialog-modal__header__title'>
<FormattedMessage id='status.embed' defaultMessage='Get embed code' />
</span>
<Button secondary onClick={onClose}>
<FormattedMessage
id='confirmation_modal.cancel'
defaultMessage='Cancel'
/>
</Button>
</div>
<div className='dialog-modal__content'>
<div className='dialog-modal__content__form'>
<FormattedMessage
id='embed.instructions'
defaultMessage='Embed this status on your website by copying the code below.'
/>
<CopyPasteText value={oembed?.html ?? ''} />
<FormattedMessage
id='embed.preview'
defaultMessage='Here is what it will look like:'
/>
<iframe
frameBorder='0'
ref={iframeRef}
sandbox='allow-scripts allow-same-origin'
title='Preview'
/>
</div>
</div>
</div>
);
};
// eslint-disable-next-line import/no-default-export
export default EmbedModal;