diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx index 351ca1d0..b0bc78c1 100644 --- a/src/view/com/composer/text-input/TextInput.web.tsx +++ b/src/view/com/composer/text-input/TextInput.web.tsx @@ -9,7 +9,7 @@ import Hardbreak from '@tiptap/extension-hard-break' import {Mention} from '@tiptap/extension-mention' import {Paragraph} from '@tiptap/extension-paragraph' import {Placeholder} from '@tiptap/extension-placeholder' -import {Text} from '@tiptap/extension-text' +import {Text as TiptapText} from '@tiptap/extension-text' import isEqual from 'lodash.isequal' import {createSuggestion} from './web/Autocomplete' import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle' @@ -19,6 +19,10 @@ import {LinkDecorator} from './web/LinkDecorator' import {generateJSON} from '@tiptap/html' import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete' import {usePalette} from '#/lib/hooks/usePalette' +import {Portal} from '#/components/Portal' +import {Text} from '../../util/text/Text' +import {Trans} from '@lingui/macro' +import Animated, {FadeIn, FadeOut} from 'react-native-reanimated' export interface TextInputRef { focus: () => void @@ -73,7 +77,7 @@ export const TextInput = React.forwardRef(function TextInputImpl( Placeholder.configure({ placeholder, }), - Text, + TiptapText, History, Hardbreak, ], @@ -93,6 +97,41 @@ export const TextInput = React.forwardRef(function TextInputImpl( } }, [onPhotoPasted]) + React.useEffect(() => { + const handleDrop = (event: DragEvent) => { + const transfer = event.dataTransfer + if (transfer) { + const items = transfer.items + + getImageFromUri(items, (uri: string) => { + textInputWebEmitter.emit('photo-pasted', uri) + }) + } + + event.preventDefault() + setIsDropping(false) + } + const handleDragOver = (event: DragEvent) => { + const transfer = event.dataTransfer + if (transfer && transfer.types.includes('Files')) { + setIsDropping(true) + } + } + const handleDragLeave = (_event: DragEvent) => { + setIsDropping(false) + } + + document.body.addEventListener('drop', handleDrop) + document.body.addEventListener('dragover', handleDragOver) + document.body.addEventListener('dragleave', handleDragLeave) + + return () => { + document.body.removeEventListener('drop', handleDrop) + document.body.removeEventListener('dragover', handleDragOver) + document.body.removeEventListener('dragleave', handleDragLeave) + } + }, [setIsDropping]) + const editor = useEditor( { extensions, @@ -117,32 +156,6 @@ export const TextInput = React.forwardRef(function TextInputImpl( return true } }, - handleDOMEvents: { - dragover: (_, event) => { - const transfer = event.dataTransfer - if (transfer && transfer.types.includes('Files')) { - setIsDropping(true) - } - }, - dragleave: (_, _event) => { - setIsDropping(false) - }, - drop: (_, event) => { - const transfer = event.dataTransfer - if (transfer) { - const items = transfer.items - - if (items.length > 0) { - event.preventDefault() - getImageFromUri(items, (uri: string) => { - textInputWebEmitter.emit('photo-pasted', uri) - }) - } - } - - setIsDropping(false) - }, - }, }, content: generateJSON(richtext.text.toString(), extensions), autofocus: 'end', @@ -208,13 +221,32 @@ export const TextInput = React.forwardRef(function TextInputImpl( })) return ( - - + <> + + + {isDropping && ( - + + + + + Drop to add images + + + + )} - + ) }) @@ -246,16 +278,30 @@ const styles = StyleSheet.create({ marginBottom: 10, }, dropContainer: { + backgroundColor: '#0007', pointerEvents: 'none', + alignItems: 'center', + justifyContent: 'center', position: 'absolute', - borderWidth: 4, - borderRadius: 8, - borderStyle: 'dashed', + padding: 16, top: 0, bottom: 0, left: 0, right: 0, }, + dropModal: { + // @ts-ignore web only + boxShadow: 'rgba(0, 0, 0, 0.3) 0px 5px 20px', + padding: 8, + borderWidth: 1, + borderRadius: 8, + }, + dropText: { + padding: 32, + borderStyle: 'dashed', + borderRadius: 8, + borderWidth: 2, + }, }) function getImageFromUri(