1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-30 10:36:35 +02:00

Desktop: Fixes #9826: Fix drag-and-drop of images and text in the rich text editor (#9827)

This commit is contained in:
Henry Heino 2024-02-02 14:57:26 -08:00 committed by GitHub
parent 43d36f9415
commit 987417502f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 44 additions and 26 deletions

View File

@ -30,6 +30,7 @@ import shouldPasteResources from './utils/shouldPasteResources';
import lightTheme from '@joplin/lib/themes/light';
import { Options as NoteStyleOptions } from '@joplin/renderer/noteStyle';
import markupRenderOptions from '../../utils/markupRenderOptions';
import { DropHandler } from '../../utils/useDropHandler';
const md5 = require('md5');
const { clipboard } = require('electron');
const supportedLocales = require('./supportedLocales');
@ -93,7 +94,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
const props_onMessage = useRef(null);
props_onMessage.current = props.onMessage;
const props_onDrop = useRef(null);
const props_onDrop = useRef<DropHandler|null>(null);
props_onDrop.current = props.onDrop;
const markupToHtml = useRef(null);
@ -706,16 +707,21 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
if (editable) openEditDialog(editor, markupToHtml, dispatchDidUpdate, editable);
});
// This is triggered when an external file is dropped on the editor
editor.on('drop', (event) => {
// Prevent the message "Dropped file type is not
// supported" to show up. It was added in a recent
// TinyMCE version and doesn't apply since we do support
// Prevent the message "Dropped file type is not supported" from showing up.
// It was added in TinyMCE 5.4 and doesn't apply since we do support
// the file type.
// https://stackoverflow.com/questions/64782955/tinymce-inline-drag-and-drop-image-upload-not-working
event.preventDefault();
props_onDrop.current(event);
//
// See https://stackoverflow.com/questions/64782955/tinymce-inline-drag-and-drop-image-upload-not-working
//
// The other suggested solution, setting block_unsupported_drop to false,
// causes all dropped files to be placed at the top of the document.
//
// Because .preventDefault cancels TinyMCE's own drop handler, we only
// call .preventDefault if Joplin handled the event:
if (props_onDrop.current(event)) {
event.preventDefault();
}
});
editor.on('ObjectResized', (event) => {

View File

@ -5,6 +5,7 @@ import { MarkupLanguage } from '@joplin/renderer';
import { RenderResult, RenderResultPluginAsset } from '@joplin/renderer/types';
import { Dispatch } from 'redux';
import { ProcessResultsRow } from '@joplin/lib/services/search/SearchEngine';
import { DropHandler } from './useDropHandler';
export interface AllAssetsOptions {
contentMaxWidthTarget?: string;
@ -113,7 +114,7 @@ export interface NoteBodyEditorProps {
resourceDirectory: string;
locale: string;
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
onDrop: Function;
onDrop: DropHandler;
noteToolbarButtonInfos: ToolbarButtonInfo[];
plugins: PluginStates;
fontSize: number;

View File

@ -1,36 +1,44 @@
import { useCallback } from 'react';
import Note from '@joplin/lib/models/Note';
import { DragEvent as ReactDragEvent } from 'react';
interface HookDependencies {
editorRef: any;
}
export default function useDropHandler(dependencies: HookDependencies) {
// Returns true if Joplin handled the event
export type DropHandler = (event: DragEvent|ReactDragEvent)=> boolean;
export default function useDropHandler(dependencies: HookDependencies): DropHandler {
const { editorRef } = dependencies;
return useCallback(async (event: any) => {
if (!event.dataTransfer) return;
return useCallback((event: DragEvent|ReactDragEvent) => {
if (!event.dataTransfer) return false;
const dt = event.dataTransfer;
const createFileURL = event.altKey;
if (dt.types.indexOf('text/x-jop-note-ids') >= 0) {
const noteIds = JSON.parse(dt.getData('text/x-jop-note-ids'));
const noteMarkdownTags = [];
for (let i = 0; i < noteIds.length; i++) {
const note = await Note.load(noteIds[i]);
noteMarkdownTags.push(Note.markdownTag(note));
}
editorRef.current.execCommand({
name: 'dropItems',
value: {
type: 'notes',
markdownTags: noteMarkdownTags,
},
});
const dropNotes = async () => {
const noteMarkdownTags = [];
for (let i = 0; i < noteIds.length; i++) {
const note = await Note.load(noteIds[i]);
noteMarkdownTags.push(Note.markdownTag(note));
}
return;
editorRef.current.execCommand({
name: 'dropItems',
value: {
type: 'notes',
markdownTags: noteMarkdownTags,
},
});
};
void dropNotes();
return true;
}
const files = dt.files;
@ -50,7 +58,10 @@ export default function useDropHandler(dependencies: HookDependencies) {
createFileURL: createFileURL,
},
});
return true;
}
return false;
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
}, []);
}