Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 41 additions & 15 deletions packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ let markupToHtml_ = new MarkupToHtml();
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
function stripMarkup(markupLanguage: number, markup: string, options: any = null) {
if (!markupToHtml_) markupToHtml_ = new MarkupToHtml();
return markupToHtml_.stripMarkup(markupLanguage, markup, options);
return markupToHtml_.stripMarkup(markupLanguage, markup, options);
}

interface LastOnChangeEventInfo {
Expand All @@ -97,17 +97,17 @@ let dispatchDidUpdateIID_: any = null;
let changeId_ = 1;

const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {
const [editorContainer, setEditorContainer] = useState<HTMLDivElement|null>(null);
const [editorContainer, setEditorContainer] = useState<HTMLDivElement | null>(null);
const editorContainerDom = useDocument(editorContainer);
const [editor, setEditor] = useState<Editor|null>(null);
const [editor, setEditor] = useState<Editor | null>(null);
const [scriptLoaded, setScriptLoaded] = useState(false);
const [editorReady, setEditorReady] = useState(false);
const [draggingStarted, setDraggingStarted] = useState(false);

const props_onMessage = useRef(null);
props_onMessage.current = props.onMessage;

const props_onDrop = useRef<DropHandler|null>(null);
const props_onDrop = useRef<DropHandler | null>(null);
props_onDrop.current = props.onDrop;

const markupToHtml = useRef(null);
Expand Down Expand Up @@ -364,7 +364,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {
// };

useEffect(() => {
if (!editorContainerDom) return () => {};
if (!editorContainerDom) return () => { };

let cancelled = false;

Expand Down Expand Up @@ -412,7 +412,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {
const { resetModifiedTitles: resetLinkTooltips } = useLinkTooltips(editor);

useEffect(() => {
if (!editorContainerDom) return () => {};
if (!editorContainerDom) return () => { };
const theme = themeStyle(props.themeId);
const backgroundColor = props.whiteBackgroundNoteRendering ? lightTheme.backgroundColor : theme.backgroundColor;

Expand Down Expand Up @@ -1094,11 +1094,11 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {
const noteChangeTimeRef = useRef(Date.now());
const lastNoteIdRef = useRef(props.noteId);
useEffect(() => {
if (!editor) return () => {};
if (!editor) return () => { };

if (resourcesStatus(props.resourceInfos) !== 'ready') {
editor.setContent('');
return () => {};
return () => { };
}

let cancelled = false;
Expand Down Expand Up @@ -1201,7 +1201,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {
}, [editor, props.noteId, props.themeId, props.markupToHtml, props.allAssets, props.content, props.resourceInfos, props.contentKey, props.contentMarkupLanguage, props.whiteBackgroundNoteRendering]);

useEffect(() => {
if (!editor) return () => {};
if (!editor) return () => { };

editor.getDoc().addEventListener('click', onEditorContentClick);
return () => {
Expand All @@ -1213,7 +1213,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {
// overlay over the editor, which makes it a valid drop target. This in
// turn makes NoteEditor get the drop event and dispatch it.
useEffect(() => {
if (!editor) return () => {};
if (!editor) return () => { };

function onDragStart() {
setDraggingStarted(true);
Expand Down Expand Up @@ -1295,7 +1295,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {
const onChangeHandlerTimeoutRef = useRef<any>(null);

useEffect(() => {
if (!editor) return () => {};
if (!editor) return () => { };

function onChangeHandler() {
// First this component notifies the parent that a change is going to happen.
Expand Down Expand Up @@ -1454,12 +1454,19 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {
if (pastedHtml) { // Handles HTML
logger.info('onPaste: pasting as HTML');

const inTable = !!editor.dom.getParent(editor.selection.getNode(), 'table');

const modifiedHtml = await processPastedHtml(
pastedHtml,
prop_htmlToMarkdownRef.current,
markupToHtml.current,
inTable ? null : prop_htmlToMarkdownRef.current,
inTable ? null : markupToHtml.current,
);
editor.insertContent(modifiedHtml);

if (inTable && pastedHtml.toLowerCase().indexOf('<table') >= 0) {
editor.execCommand('mceInsertClipboardContent', false, { html: modifiedHtml });
} else {
editor.insertContent(modifiedHtml);
}
} else { // Handles plain text
logger.info('onPaste: pasting as text');
pasteAsPlainText(pastedText);
Expand All @@ -1470,6 +1477,15 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
async function onCopy(event: any) {
const selectedCells = editor.dom.select('td[data-mce-selected="1"], th[data-mce-selected="1"]');
if (selectedCells.length > 1 || editor.dom.select('tr[data-mce-selected="1"]').length > 0) {
setTimeout(() => {
const clipboardHtml = clipboard.readHTML();
if (clipboardHtml) copyHtmlToClipboard(clipboardHtml);
}, 50);
return;
}

const copiedContent = editor.selection.getContent();
if (!copiedContent) return;
copyHtmlToClipboard(copiedContent);
Expand All @@ -1478,6 +1494,16 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
async function onCut(event: any) {
const selectedCells = editor.dom.select('td[data-mce-selected="1"], th[data-mce-selected="1"]');
if (selectedCells.length > 1 || editor.dom.select('tr[data-mce-selected="1"]').length > 0) {
setTimeout(() => {
const clipboardHtml = clipboard.readHTML();
if (clipboardHtml) copyHtmlToClipboard(clipboardHtml);
onChangeHandler();
}, 50);
return;
}

event.preventDefault();
const selectedContent = editor.selection.getContent();
if (!selectedContent) return;
Expand Down Expand Up @@ -1683,7 +1709,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {
{renderDisabledOverlay()}
{renderLeftExtraToolbarButtons()}
{renderRightExtraToolbarButtons()}
<div style={{ width: '100%', height: '100%' }} id={containerId} ref={setEditorContainer}/>
<div style={{ width: '100%', height: '100%' }} id={containerId} ref={setEditorContainer} />
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,26 @@ export default function(editor: Editor, plugins: PluginStates, dispatch: Dispatc
linkToCopy: linkUrl,
linkToOpen: linkUrl,
textToCopy: null,
htmlToCopy: editor.selection ? editor.selection.getContent() : '',
htmlToCopy: (() => {
if (!editor.selection) return '';
const selectedCells = editor.dom.select('td[data-mce-selected="1"], th[data-mce-selected="1"]');
if (selectedCells.length > 1 || editor.dom.select('tr[data-mce-selected="1"]').length > 0) {
return 'table-selected';
}
return editor.selection.getContent();
})(),
insertContent: (content: string) => {
editor.insertContent(content);
},
isReadOnly: false,
fireEditorEvent: (event: TinyMceEditorEvents) => {
editor.fire(event);
fireEditorEvent: (event: TinyMceEditorEvents|string) => {
if (event === 'execCommandCopy') {
editor.getDoc().execCommand('copy');
} else if (event === 'execCommandCut') {
editor.getDoc().execCommand('cut');
} else {
editor.fire(event as TinyMceEditorEvents);
}
},
htmlToMd,
mdToHtml,
Expand Down
14 changes: 11 additions & 3 deletions packages/app-desktop/gui/NoteEditor/utils/contextMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,23 @@ export function menuItems(dispatch: Function): ContextMenuItems {
cut: {
label: _('Cut'),
onAction: async (options: ContextMenuOptions) => {
handleCopyToClipboard(options);
options.insertContent('');
if (options.htmlToCopy === 'table-selected') {
options.fireEditorEvent('execCommandCut');
} else {
handleCopyToClipboard(options);
options.insertContent('');
}
},
isActive: (itemType: ContextMenuItemType, options: ContextMenuOptions) => itemType !== ContextMenuItemType.Image && (!options.isReadOnly && (!!options.textToCopy || !!options.htmlToCopy)),
},
copy: {
label: _('Copy'),
onAction: async (options: ContextMenuOptions) => {
handleCopyToClipboard(options);
if (options.htmlToCopy === 'table-selected') {
options.fireEditorEvent('execCommandCopy');
} else {
handleCopyToClipboard(options);
}
},
isActive: (itemType: ContextMenuItemType, options: ContextMenuOptions) => itemType !== ContextMenuItemType.Image && (!!options.textToCopy || !!options.htmlToCopy),
},
Expand Down
Loading