import React from 'react'; import {getValidMediaType, canDropMedia, dragEventShouldShowDropZone} from './Editor3Component'; import {moveBlock, dragDrop, embed} from '../actions/editor3'; import {getEmbedObject} from './embeds/EmbedInput'; import {htmlComesFromDraftjsEditor} from 'core/editor3/helpers/htmlComesFromDraftjsEditor'; import {htmlIsPlainTextDragged} from 'core/editor3/helpers/htmlIsPlainTextDragged'; import {EDITOR_BLOCK_TYPE} from '../constants'; export function isEditorBlockEvent(event) { return event.originalEvent.dataTransfer.types.indexOf(EDITOR_BLOCK_TYPE) > -1; } export function getEditorBlock(event) { return event.originalEvent.dataTransfer.getData(EDITOR_BLOCK_TYPE); } function embedShouldBeCreated(html, editorProps): boolean { if (!editorProps.editorFormat.includes('embed')) { return false; } const comingFromDraftJS = htmlComesFromDraftjsEditor(html); const shouldEmbedBeCreated = comingFromDraftJS ? false : !htmlIsPlainTextDragged(html); return shouldEmbedBeCreated; } function isHtmlTextAndShouldCreateEmbed(event, mediaType, editorProps): boolean { if (mediaType !== 'text/html') { return false; } const html = event.originalEvent.dataTransfer.getData(mediaType); return embedShouldBeCreated(html, editorProps); } interface IProps { dispatch(action: any); editorProps: any; className?: string; } interface IState { over: boolean; } class BaseUnstyledComponent extends React.Component { static propTypes: any; static defaultProps: any; getDropBlockKey: any; dropInsertionMode: any; leaveTimeout: any; div: any; constructor(props) { super(props); this.onDrop = this.onDrop.bind(this); this.onDragOver = this.onDragOver.bind(this); this.onDragLeave = this.onDragLeave.bind(this); this.state = {over: false}; } onDrop(event) { this.setState({over: false}); let handled = false; const block = getEditorBlock(event); if (typeof block === 'string' && block.length > 0) { // existing media item dropped to another place this.props.dispatch(moveBlock(block, this.getDropBlockKey(), this.dropInsertionMode)); handled = true; } else { const {dataTransfer} = event.originalEvent; const mediaType = getValidMediaType(event.originalEvent); const blockKey = this.getDropBlockKey(); const link = event.originalEvent.dataTransfer.getData('URL'); if (canDropMedia(event, this.props.editorProps) && (mediaType === 'Files' || mediaType.includes('application/superdesk'))) { this.props.dispatch(dragDrop(dataTransfer, mediaType, blockKey)); handled = true; } else if ( typeof link === 'string' && link.startsWith('http') && this.props.editorProps.editorFormat.includes('embed') ) { getEmbedObject(link) .then((oEmbed) => { this.props.dispatch(embed(oEmbed, blockKey)); }); handled = true; } else if (isHtmlTextAndShouldCreateEmbed(event, mediaType, this.props.editorProps)) { this.props.dispatch(embed(event.originalEvent.dataTransfer.getData(mediaType), blockKey)); handled = true; } else { console.warn('unsupported media type on drop', mediaType); } } if (handled) { event.preventDefault(); event.stopPropagation(); } } onDragOver(event) { if (!dragEventShouldShowDropZone(event.originalEvent)) { return; } if (this.leaveTimeout) { clearTimeout(this.leaveTimeout); this.leaveTimeout = null; } event.preventDefault(); event.stopPropagation(); this.setState({over: true}); } onDragLeave(event) { if (!dragEventShouldShowDropZone(event.originalEvent)) { return; } event.stopPropagation(); if (this.state.over && !this.leaveTimeout) { this.leaveTimeout = setTimeout(() => { this.setState({over: false}); this.leaveTimeout = null; }, 50); // avoid placeholder flickering } } componentDidMount() { $(this.div).on('drop', this.onDrop); $(this.div).on('dragleave', this.onDragLeave); $(this.div).on('dragover dragenter', this.onDragOver); } componentWillUnmount() { $(this.div).off(); } } export default BaseUnstyledComponent;