1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-11-27 08:21:03 +02:00

Desktop: Fixes #4767: Create own copy of images while pasting (#4852)

This commit is contained in:
Nishant Mittal 2021-05-03 19:43:51 +05:30 committed by GitHub
parent a6caa357c8
commit eb82ae87ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 2 deletions

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, handlePasteEvent } from '../../utils/resourceHandling';
import { resourcesStatus, commandAttachFileToBody, handlePasteEvent, processPastedHtml } from '../../utils/resourceHandling';
import useScroll from './utils/useScroll';
import styles_ from './styles';
import CommandService from '@joplin/lib/services/CommandService';
@ -1032,6 +1032,14 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
// 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.
const pastedHtml = clipboard.readHTML();
if (pastedHtml) {
event.preventDefault();
const modifiedHtml = await processPastedHtml(pastedHtml);
editor.insertContent(modifiedHtml);
}
window.requestAnimationFrame(() => editor.undoManager.add());
onChangeHandler();
}

View File

@ -6,6 +6,7 @@ const bridge = require('electron').remote.require('./bridge').default;
const Menu = bridge().Menu;
const MenuItem = bridge().MenuItem;
import Resource from '@joplin/lib/models/Resource';
import { processPastedHtml } from './resourceHandling';
const fs = require('fs-extra');
const { clipboard } = require('electron');
const { toSystemSlashes } = require('@joplin/lib/path-utils');
@ -112,7 +113,13 @@ export function menuItems(): ContextMenuItems {
paste: {
label: _('Paste'),
onAction: async (options: ContextMenuOptions) => {
const content = clipboard.readHTML() ? clipboard.readHTML() : clipboard.readText();
const pastedHtml = clipboard.readHTML();
let content = pastedHtml ? pastedHtml : clipboard.readText();
if (pastedHtml) {
content = await processPastedHtml(pastedHtml);
}
options.insertContent(content);
},
isActive: (_itemType: ContextMenuItemType, options: ContextMenuOptions) => !options.isReadOnly && (!!clipboard.readText() || !!clipboard.readHTML()),

View File

@ -6,10 +6,13 @@ import Resource from '@joplin/lib/models/Resource';
const bridge = require('electron').remote.require('./bridge').default;
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
import { reg } from '@joplin/lib/registry';
import htmlUtils from '@joplin/lib/htmlUtils';
import Logger from '@joplin/lib/Logger';
const joplinRendererUtils = require('@joplin/renderer').utils;
const { clipboard } = require('electron');
const mimeUtils = require('@joplin/lib/mime-utils.js').mime;
const md5 = require('md5');
const path = require('path');
export async function handleResourceDownloadMode(noteBody: string) {
if (noteBody && Setting.value('sync.resourceDownloadMode') === 'auto') {
@ -125,3 +128,44 @@ export async function handlePasteEvent(event: any) {
}
return output;
}
export async function processPastedHtml(html: string) {
const allImageUrls: string[] = [];
const mappedResources: Record<string, string> = {};
htmlUtils.replaceImageUrls(html, (src: string) => {
allImageUrls.push(src);
});
for (const imageSrc of allImageUrls) {
if (!mappedResources[imageSrc]) {
try {
if (imageSrc.startsWith('file')) {
const imageFilePath = path.normalize(imageSrc.substr(7));
const resourceDirPath = path.normalize(Setting.value('resourceDir'));
if (imageFilePath.startsWith(resourceDirPath)) {
mappedResources[imageSrc] = imageSrc;
} else {
const createdResource = await shim.createResourceFromPath(imageFilePath);
mappedResources[imageSrc] = `file://${Resource.fullPath(createdResource)}`;
}
} else {
const filePath = `${Setting.value('tempDir')}/${md5(Date.now() + Math.random())}`;
await shim.fetchBlob(imageSrc, { path: filePath });
const createdResource = await shim.createResourceFromPath(filePath);
await shim.fsDriver().remove(filePath);
mappedResources[imageSrc] = `file://${Resource.fullPath(createdResource)}`;
}
} catch (err) {
const logger = Logger.create('resourceHandling');
logger.warn(`Error creating a resource for ${imageSrc}.`, err);
mappedResources[imageSrc] = imageSrc;
}
}
}
return htmlUtils.replaceImageUrls(html, (src: string) => {
return mappedResources[src];
});
}