117 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			117 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;
 |