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

Desktop: WYSIWYG: Allow pasting images in editor

This commit is contained in:
Laurent Cozic 2020-05-11 19:26:04 +01:00
parent dacf6377ae
commit 05adb06aeb
3 changed files with 51 additions and 39 deletions

View File

@ -3,7 +3,7 @@ import { useState, useEffect, useRef, forwardRef, useCallback, useImperativeHand
// eslint-disable-next-line no-unused-vars
import { EditorCommand, NoteBodyEditorProps } from '../../utils/types';
import { commandAttachFileToBody } from '../../utils/resourceHandling';
import { commandAttachFileToBody, handlePasteEvent } from '../../utils/resourceHandling';
import { ScrollOptions, ScrollOptionTypes } from '../../utils/types';
import { textOffsetToCursorPosition, useScrollHandler, useRootWidth, usePrevious, lineLeftSpaces, selectionRangeCurrentLine, selectionRangePreviousLine, currentTextOffset, textOffsetSelection, selectedText, useSelectionRange } from './utils';
import useListIdent from './utils/useListIdent';
@ -15,12 +15,9 @@ const AceEditorReact = require('react-ace').default;
const { bridge } = require('electron').remote.require('./bridge');
const Note = require('lib/models/Note.js');
const { clipboard } = require('electron');
const mimeUtils = require('lib/mime-utils.js').mime;
const Setting = require('lib/models/Setting.js');
const NoteTextViewer = require('../../../NoteTextViewer.min');
const shared = require('lib/components/shared/note-screen-shared.js');
const md5 = require('md5');
const { shim } = require('lib/shim.js');
const Menu = bridge().Menu;
const MenuItem = bridge().MenuItem;
const markdownUtils = require('lib/markdownUtils');
@ -332,29 +329,10 @@ function AceEditor(props: NoteBodyEditorProps, ref: any) {
}, [editor, props.content, addListItem, wrapSelectionWithStrings, selectionRangeCurrentLine, aceEditor_change, setEditorPercentScroll, setViewerPercentScroll, resetScroll, renderedBody]);
const onEditorPaste = useCallback(async (event: any = null) => {
const formats = clipboard.availableFormats();
for (let i = 0; i < formats.length; i++) {
const format = formats[i].toLowerCase();
const formatType = format.split('/')[0];
const position = currentTextOffset(editor, props.content);
if (formatType === 'image') {
if (event) event.preventDefault();
const image = clipboard.readImage();
const fileExt = mimeUtils.toFileExtension(format);
const filePath = `${Setting.value('tempDir')}/${md5(Date.now())}.${fileExt}`;
await shim.writeImageToFile(image, format, filePath);
const newBody = await commandAttachFileToBody(props.content, [filePath], { position });
await shim.fsDriver().remove(filePath);
aceEditor_change(newBody);
}
}
}, [editor, props.content, aceEditor_change]);
const resourceMds = await handlePasteEvent(event);
if (!resourceMds.length) return;
wrapSelectionWithStrings('', '', resourceMds.join('\n'));
}, [wrapSelectionWithStrings]);
const onEditorKeyDown = useCallback((event: any) => {
setLastKeys(prevLastKeys => {

View File

@ -1,7 +1,7 @@
import * as React from 'react';
import { useState, useEffect, useCallback, useRef, forwardRef, useImperativeHandle } from 'react';
import { ScrollOptions, ScrollOptionTypes, EditorCommand, NoteBodyEditorProps } from '../../utils/types';
import { resourcesStatus, commandAttachFileToBody } from '../../utils/resourceHandling';
import { resourcesStatus, commandAttachFileToBody, handlePasteEvent } from '../../utils/resourceHandling';
import useScroll from './utils/useScroll';
import { menuItems, ContextMenuOptions, ContextMenuItemType } from '../../utils/contextMenu';
const { MarkupToHtml } = require('lib/joplin-renderer');
@ -879,18 +879,24 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
}
async function onPaste(event:any) {
const pastedText = event.clipboardData.getData('text');
if (BaseItem.isMarkdownTag(pastedText)) { // Paste a link to a note
event.preventDefault();
const result = await markupToHtml.current(MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN, pastedText, markupRenderOptions({ bodyOnly: true }));
const resourceMds = await handlePasteEvent(event);
if (resourceMds.length) {
const result = await markupToHtml.current(MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN, resourceMds.join('\n'), markupRenderOptions({ bodyOnly: true }));
editor.insertContent(result.html);
} else { // Paste regular text
// HACK: TinyMCE doesn't add an undo step when pasting, for unclear reasons
// so we manually add it here. We also can't do it immediately it seems, or
// else nothing is added to the stack, so do it on the next frame.
window.requestAnimationFrame(() => editor.undoManager.add());
onChangeHandler();
} else {
const pastedText = event.clipboardData.getData('text');
if (BaseItem.isMarkdownTag(pastedText)) { // Paste a link to a note
event.preventDefault();
const result = await markupToHtml.current(MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN, pastedText, markupRenderOptions({ bodyOnly: true }));
editor.insertContent(result.html);
} else { // Paste regular text
// HACK: TinyMCE doesn't add an undo step when pasting, for unclear reasons
// so we manually add it here. We also can't do it immediately it seems, or
// else nothing is added to the stack, so do it on the next frame.
window.requestAnimationFrame(() => editor.undoManager.add());
onChangeHandler();
}
}
}

View File

@ -7,6 +7,9 @@ const { bridge } = require('electron').remote.require('./bridge');
const ResourceFetcher = require('lib/services/ResourceFetcher.js');
const { reg } = require('lib/registry.js');
const joplinRendererUtils = require('lib/joplin-renderer').utils;
const { clipboard } = require('electron');
const mimeUtils = require('lib/mime-utils.js').mime;
const md5 = require('md5');
export async function handleResourceDownloadMode(noteBody: string) {
if (noteBody && Setting.value('sync.resourceDownloadMode') === 'auto') {
@ -97,3 +100,28 @@ export function resourcesStatus(resourceInfos: any) {
}
return joplinRendererUtils.resourceStatusName(lowestIndex);
}
export async function handlePasteEvent(event:any) {
const output = [];
const formats = clipboard.availableFormats();
for (let i = 0; i < formats.length; i++) {
const format = formats[i].toLowerCase();
const formatType = format.split('/')[0];
if (formatType === 'image') {
if (event) event.preventDefault();
const image = clipboard.readImage();
const fileExt = mimeUtils.toFileExtension(format);
const filePath = `${Setting.value('tempDir')}/${md5(Date.now())}.${fileExt}`;
await shim.writeImageToFile(image, format, filePath);
const md = await commandAttachFileToBody('', [filePath]);
await shim.fsDriver().remove(filePath);
output.push(md);
}
}
return output;
}