Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MM-26675] Copy paste applies l ink markdown in edit_textbox #27097

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
39 changes: 36 additions & 3 deletions webapp/channels/src/components/edit_post/edit_post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See LICENSE.txt for license information.

import classNames from 'classnames';
import isNil from 'lodash/isNil';
import React, {useCallback, useEffect, useRef, useState} from 'react';
import {useIntl} from 'react-intl';

Expand All @@ -18,15 +19,18 @@ import Textbox from 'components/textbox';
import type {TextboxClass, TextboxElement} from 'components/textbox';

import {AppEvents, Constants, ModalIdentifiers, StoragePrefixes} from 'utils/constants';
import {execCommandInsertText} from 'utils/exec_commands';
import * as Keyboard from 'utils/keyboard';
import {applyMarkdown} from 'utils/markdown/apply_markdown';
import type {ApplyMarkdownOptions} from 'utils/markdown/apply_markdown';
import {
formatGithubCodePaste,
formatMarkdownLinkMessage,
formatMarkdownMessage,
getHtmlTable,
hasHtmlLink,
isGitHubCodeBlock,
isTextUrl,
} from 'utils/paste';
import {postMessageOnKeyPress, splitMessageBasedOnCaretPosition} from 'utils/post_utils';
import * as Utils from 'utils/utils';
Expand Down Expand Up @@ -80,7 +84,7 @@ export type Props = {

export type State = {
editText: string;
selectionRange: {start: number; end: number};
selectionRange: { start: number; end: number };
postError: React.ReactNode;
errorClass: string | null;
showEmojiPicker: boolean;
Expand Down Expand Up @@ -112,7 +116,7 @@ const EditPost = ({editingPost, actions, canEditPost, config, channelId, draft,
// If we would just use the editText value from the state it would be a stale since it is encapsuled in the
// function closure on initial render
const draftRef = useRef<PostDraft>(draft);
const saveDraftFrame = useRef<number|null>();
const saveDraftFrame = useRef<number | null>();

const draftStorageId = `${StoragePrefixes.EDIT_DRAFT}${editingPost.postId}`;

Expand Down Expand Up @@ -157,6 +161,35 @@ const EditPost = ({editingPost, actions, canEditPost, config, channelId, draft,
// just a helper so it's not always needed to update with setting both properties to the same value
const setCaretPosition = (position: number) => setSelectionRange({start: position, end: position});

useEffect(() => {
function onPaste(event: ClipboardEvent) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a pasteHandler in webapp/channels/src/utils/paste.tsx.

Is this something we can reuse in any way? or are there strong reasons to keep this one different? (I see it is for the most part the same, but missing some things).

Copy link
Author

@cyrusjc cyrusjc Jun 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no major differences besides the fact that the post textbox uses some props that don't exist in webapp/channels/src/components/edit_post/edit_post.tsx which is passed as arguments to pasteHandler(). An alternative method is to modify pasteHandler() to replace this logic which I originally didn't want to do but it does make sense for the logic for the post textbox and the edit textbox to be the same.

How would you want to approach this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's go with updating the behavior in pasteHandler. Without having looked at it much, what I would do is pass a special location from this component (maybe add it to the Locations constants as "EDIT"), and handle the differences based on that.

const {clipboardData, target} = event;

if (!clipboardData || !clipboardData.items || !target || (target as TextboxElement)?.id !== 'edit_textbox') {
return;
}

const {selectionStart, selectionEnd} = target as TextboxElement;

const hasSelection = !isNil(selectionStart) && !isNil(selectionEnd) && selectionStart < selectionEnd;
const hasTextUrl = isTextUrl(clipboardData);

const shouldApplyLinkMarkdown = hasSelection && hasTextUrl;
event.preventDefault();

const message = editText;
if (shouldApplyLinkMarkdown) {
const formattedLink = formatMarkdownLinkMessage({selectionStart, selectionEnd, message, clipboardData});
execCommandInsertText(formattedLink);
}
}

document.addEventListener('paste', onPaste);
return () => {
document.removeEventListener('paste', onPaste);
};
});

const handlePaste = useCallback((e: ClipboardEvent) => {
const {clipboardData, target} = e;
if (
Expand Down Expand Up @@ -218,7 +251,7 @@ const EditPost = ({editingPost, actions, canEditPost, config, channelId, draft,
setSelectionRange({start: res.selectionStart, end: res.selectionEnd});
};

const handleRefocusAndExit = (refocusId: string|null) => {
const handleRefocusAndExit = (refocusId: string | null) => {
if (refocusId) {
const element = document.getElementById(refocusId);
element?.focus();
Expand Down
Loading