mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
Desktop: Add 'Paste as text' to the Context menu of the Rich Text Editor (#7769)
This commit is contained in:
parent
7d7b7ed6f3
commit
dd86940c6b
@ -221,6 +221,7 @@ packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/openEditDialog.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteEditor.js
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -209,6 +209,7 @@ packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/openEditDialog.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteEditor.js
|
||||
|
@ -24,6 +24,7 @@ import { MarkupToHtmlOptions } from '../../utils/useMarkupToHtml';
|
||||
import { themeStyle } from '@joplin/lib/theme';
|
||||
import { loadScript } from '../../../utils/loadScript';
|
||||
import bridge from '../../../../services/bridge';
|
||||
import { TinyMceEditorEvents } from './utils/types';
|
||||
const { clipboard } = require('electron');
|
||||
const supportedLocales = require('./supportedLocales');
|
||||
|
||||
@ -169,7 +170,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
const nodeName = event.target ? event.target.nodeName : '';
|
||||
|
||||
if (nodeName === 'INPUT' && event.target.getAttribute('type') === 'checkbox') {
|
||||
editor.fire('joplinChange');
|
||||
editor.fire(TinyMceEditorEvents.JoplinChange);
|
||||
dispatchDidUpdate(editor);
|
||||
}
|
||||
|
||||
@ -261,7 +262,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
},
|
||||
replaceSelection: (value: any) => {
|
||||
editor.selection.setContent(value);
|
||||
editor.fire('joplinChange');
|
||||
editor.fire(TinyMceEditorEvents.JoplinChange);
|
||||
dispatchDidUpdate(editor);
|
||||
|
||||
// It doesn't make sense but it seems calling setContent
|
||||
@ -270,7 +271,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
// https://github.com/tinymce/tinymce/issues/3745
|
||||
window.requestAnimationFrame(() => editor.undoManager.add());
|
||||
},
|
||||
pasteAsText: () => editor.fire('pasteAsText'),
|
||||
pasteAsText: () => editor.fire(TinyMceEditorEvents.PasteAsText),
|
||||
};
|
||||
|
||||
if (additionalCommands[cmd.name]) {
|
||||
@ -674,7 +675,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
|
||||
editor.on('ObjectResized', function(event: any) {
|
||||
if (event.target.nodeName === 'IMG') {
|
||||
editor.fire('joplinChange');
|
||||
editor.fire(TinyMceEditorEvents.JoplinChange);
|
||||
dispatchDidUpdate(editor);
|
||||
}
|
||||
});
|
||||
@ -1085,35 +1086,35 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
await onPaste(createSyntheticClipboardEventWithoutHTML());
|
||||
}
|
||||
|
||||
editor.on('keyup', onKeyUp);
|
||||
editor.on('keydown', onKeyDown);
|
||||
editor.on('keypress', onKeypress);
|
||||
editor.on('paste', onPaste);
|
||||
editor.on('pasteAsText', onPasteAsText);
|
||||
editor.on('copy', onCopy);
|
||||
editor.on(TinyMceEditorEvents.KeyUp, onKeyUp);
|
||||
editor.on(TinyMceEditorEvents.KeyDown, onKeyDown);
|
||||
editor.on(TinyMceEditorEvents.KeyPress, onKeypress);
|
||||
editor.on(TinyMceEditorEvents.Paste, onPaste);
|
||||
editor.on(TinyMceEditorEvents.PasteAsText, onPasteAsText);
|
||||
editor.on(TinyMceEditorEvents.Copy, onCopy);
|
||||
// `compositionend` means that a user has finished entering a Chinese
|
||||
// (or other languages that require IME) character.
|
||||
editor.on('compositionend', onChangeHandler);
|
||||
editor.on('cut', onCut);
|
||||
editor.on('joplinChange', onChangeHandler);
|
||||
editor.on('Undo', onChangeHandler);
|
||||
editor.on('Redo', onChangeHandler);
|
||||
editor.on('ExecCommand', onExecCommand);
|
||||
editor.on(TinyMceEditorEvents.CompositionEnd, onChangeHandler);
|
||||
editor.on(TinyMceEditorEvents.Cut, onCut);
|
||||
editor.on(TinyMceEditorEvents.JoplinChange, onChangeHandler);
|
||||
editor.on(TinyMceEditorEvents.Undo, onChangeHandler);
|
||||
editor.on(TinyMceEditorEvents.Redo, onChangeHandler);
|
||||
editor.on(TinyMceEditorEvents.ExecCommand, onExecCommand);
|
||||
|
||||
return () => {
|
||||
try {
|
||||
editor.off('keyup', onKeyUp);
|
||||
editor.off('keydown', onKeyDown);
|
||||
editor.off('keypress', onKeypress);
|
||||
editor.off('paste', onPaste);
|
||||
editor.off('pasteAsText', onPasteAsText);
|
||||
editor.off('copy', onCopy);
|
||||
editor.off('compositionend', onChangeHandler);
|
||||
editor.off('cut', onCut);
|
||||
editor.off('joplinChange', onChangeHandler);
|
||||
editor.off('Undo', onChangeHandler);
|
||||
editor.off('Redo', onChangeHandler);
|
||||
editor.off('ExecCommand', onExecCommand);
|
||||
editor.off(TinyMceEditorEvents.KeyUp, onKeyUp);
|
||||
editor.off(TinyMceEditorEvents.KeyDown, onKeyDown);
|
||||
editor.off(TinyMceEditorEvents.KeyPress, onKeypress);
|
||||
editor.off(TinyMceEditorEvents.Paste, onPaste);
|
||||
editor.off(TinyMceEditorEvents.PasteAsText, onPasteAsText);
|
||||
editor.off(TinyMceEditorEvents.Copy, onCopy);
|
||||
editor.off(TinyMceEditorEvents.CompositionEnd, onChangeHandler);
|
||||
editor.off(TinyMceEditorEvents.Cut, onCut);
|
||||
editor.off(TinyMceEditorEvents.JoplinChange, onChangeHandler);
|
||||
editor.off(TinyMceEditorEvents.Undo, onChangeHandler);
|
||||
editor.off(TinyMceEditorEvents.Redo, onChangeHandler);
|
||||
editor.off(TinyMceEditorEvents.ExecCommand, onExecCommand);
|
||||
} catch (error) {
|
||||
console.warn('Error removing events', error);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { MarkupToHtml } from '@joplin/renderer';
|
||||
import { TinyMceEditorEvents } from './types';
|
||||
const taboverride = require('taboverride');
|
||||
|
||||
interface SourceInfo {
|
||||
@ -102,7 +103,7 @@ export default function openEditDialog(editor: any, markupToHtml: any, dispatchD
|
||||
}
|
||||
|
||||
dialogApi.close();
|
||||
editor.fire('joplinChange');
|
||||
editor.fire(TinyMceEditorEvents.JoplinChange);
|
||||
dispatchDidUpdate(editor);
|
||||
},
|
||||
onClose: () => {
|
||||
|
@ -0,0 +1,15 @@
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export enum TinyMceEditorEvents {
|
||||
KeyUp = 'keyup',
|
||||
KeyDown = 'keydown',
|
||||
KeyPress = 'keypress',
|
||||
Paste = 'paste',
|
||||
PasteAsText = 'pasteAsText',
|
||||
Copy = 'copy',
|
||||
CompositionEnd = 'compositionend',
|
||||
Cut = 'cut',
|
||||
JoplinChange = 'joplinChange',
|
||||
Undo = 'Undo',
|
||||
Redo = 'Redo',
|
||||
ExecCommand = 'ExecCommand',
|
||||
}
|
@ -11,6 +11,7 @@ import convertToScreenCoordinates from '../../../../utils/convertToScreenCoordin
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
|
||||
import Resource from '@joplin/lib/models/Resource';
|
||||
import { TinyMceEditorEvents } from './types';
|
||||
|
||||
const menuUtils = new MenuUtils(CommandService.instance());
|
||||
|
||||
@ -77,6 +78,9 @@ export default function(editor: any, plugins: PluginStates, dispatch: Function)
|
||||
editor.insertContent(content);
|
||||
},
|
||||
isReadOnly: false,
|
||||
fireEditorEvent: (event: TinyMceEditorEvents) => {
|
||||
editor.fire(event);
|
||||
},
|
||||
};
|
||||
|
||||
let template = [];
|
||||
|
@ -10,6 +10,7 @@ import BaseItem from '@joplin/lib/models/BaseItem';
|
||||
import BaseModel from '@joplin/lib/BaseModel';
|
||||
import { processPastedHtml } from './resourceHandling';
|
||||
import { NoteEntity, ResourceEntity } from '@joplin/lib/services/database/types';
|
||||
import { TinyMceEditorEvents } from '../NoteBody/TinyMCE/utils/types';
|
||||
const fs = require('fs-extra');
|
||||
const { writeFile } = require('fs-extra');
|
||||
const { clipboard } = require('electron');
|
||||
@ -176,6 +177,13 @@ export function menuItems(dispatch: Function): ContextMenuItems {
|
||||
},
|
||||
isActive: (_itemType: ContextMenuItemType, options: ContextMenuOptions) => !options.isReadOnly && (!!clipboard.readText() || !!clipboard.readHTML()),
|
||||
},
|
||||
pasteAsText: {
|
||||
label: _('Paste as text'),
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
options.fireEditorEvent(TinyMceEditorEvents.PasteAsText);
|
||||
},
|
||||
isActive: (_itemType: ContextMenuItemType, options: ContextMenuOptions) => !options.isReadOnly && (!!clipboard.readText() || !!clipboard.readHTML()),
|
||||
},
|
||||
copyLinkUrl: {
|
||||
label: _('Copy Link Address'),
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
|
@ -19,6 +19,7 @@ export interface ContextMenuOptions {
|
||||
htmlToCopy: string;
|
||||
insertContent: Function;
|
||||
isReadOnly?: boolean;
|
||||
fireEditorEvent: Function;
|
||||
}
|
||||
|
||||
export interface ContextMenuItem {
|
||||
|
@ -41,6 +41,7 @@ export default function useMessageHandler(scrollWhenReady: any, setScrollWhenRea
|
||||
linkToCopy: arg0.linkToCopy || null,
|
||||
htmlToCopy: '',
|
||||
insertContent: () => { console.warn('insertContent() not implemented'); },
|
||||
fireEditorEvent: () => { console.warn('fireEditorEvent() not implemented'); },
|
||||
}, dispatch);
|
||||
|
||||
menu.popup(bridge().window());
|
||||
|
@ -59,6 +59,7 @@ export default function PdfViewer(props: Props) {
|
||||
linkToCopy: null,
|
||||
htmlToCopy: '',
|
||||
insertContent: () => { console.warn('insertContent() not implemented'); },
|
||||
fireEditorEvent: () => { console.warn('fireEditorEvent() not implemented'); },
|
||||
} as ContextMenuOptions, props.dispatch);
|
||||
|
||||
menu.popup(bridge().window());
|
||||
|
Loading…
Reference in New Issue
Block a user