fix: Improve mentions behavior

This commit is contained in:
Maksim Eltyshev
2025-08-11 13:52:17 +02:00
parent cbb00d1d59
commit 6515877eb6
9 changed files with 89 additions and 30 deletions
@@ -3,7 +3,8 @@
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
import React, { useCallback, useState, useRef } from 'react';
import keyBy from 'lodash/keyBy';
import React, { useCallback, useState, useRef, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import { Mention, MentionsInput } from 'react-mentions';
@@ -13,6 +14,7 @@ import { useClickAwayListener, useDidUpdate, useToggle } from '../../../lib/hook
import selectors from '../../../selectors';
import entryActions from '../../../entry-actions';
import { useEscapeInterceptor, useForm, useNestedRef } from '../../../hooks';
import { isUsernameChar, mentionTextToMarkup } from '../../../utils/mentions';
import { isModifierKeyPressed } from '../../../utils/event-helpers';
import UserAvatar from '../../users/UserAvatar';
@@ -36,10 +38,19 @@ const Add = React.memo(() => {
const textInputRef = useRef(null);
const [buttonRef, handleButtonRef] = useNestedRef();
const userByUsername = useMemo(
() =>
keyBy(
boardMemberships.flatMap(({ user }) => (user.username ? user : [])),
'username',
),
[boardMemberships],
);
const submit = useCallback(() => {
const cleanData = {
...data,
text: data.text.trim(),
text: mentionTextToMarkup(data.text.trim(), userByUsername),
};
if (!cleanData.text) {
@@ -50,7 +61,7 @@ const Add = React.memo(() => {
dispatch(entryActions.createCommentInCurrentCard(cleanData));
setData(DEFAULT_DATA);
selectTextField();
}, [dispatch, data, setData, selectTextField]);
}, [dispatch, data, setData, selectTextField, userByUsername]);
const handleEscape = useCallback(() => {
if (textMentionsRef.current.isOpened()) {
@@ -76,10 +87,10 @@ const Add = React.memo(() => {
const handleFieldChange = useCallback(
(_, text) => {
setData({
text,
text: !isUsernameChar(text.slice(-1)) ? mentionTextToMarkup(text, userByUsername) : text,
});
},
[setData],
[setData, userByUsername],
);
const handleFieldKeyDown = useCallback(
@@ -4,6 +4,7 @@
*/
import { dequal } from 'dequal';
import { keyBy } from 'lodash';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
@@ -15,6 +16,7 @@ import { useClickAwayListener } from '../../../lib/hooks';
import selectors from '../../../selectors';
import entryActions from '../../../entry-actions';
import { useForm, useNestedRef } from '../../../hooks';
import { isUsernameChar, mentionTextToMarkup } from '../../../utils/mentions';
import { focusEnd } from '../../../utils/element-helpers';
import { isModifierKeyPressed } from '../../../utils/event-helpers';
import UserAvatar from '../../users/UserAvatar';
@@ -48,10 +50,19 @@ const Edit = React.memo(({ commentId, onClose }) => {
const [submitButtonRef, handleSubmitButtonRef] = useNestedRef();
const [cancelButtonRef, handleCancelButtonRef] = useNestedRef();
const userByUsername = useMemo(
() =>
keyBy(
boardMemberships.flatMap(({ user }) => (user.username ? user : [])),
'username',
),
[boardMemberships],
);
const submit = useCallback(() => {
const cleanData = {
...data,
text: data.text.trim(),
text: mentionTextToMarkup(data.text.trim(), userByUsername),
};
if (cleanData.text && !dequal(cleanData, defaultData)) {
@@ -59,7 +70,7 @@ const Edit = React.memo(({ commentId, onClose }) => {
}
onClose();
}, [commentId, onClose, dispatch, defaultData, data]);
}, [commentId, onClose, dispatch, defaultData, data, userByUsername]);
const handleSubmit = useCallback(() => {
submit();
@@ -68,10 +79,10 @@ const Edit = React.memo(({ commentId, onClose }) => {
const handleFieldChange = useCallback(
(_, text) => {
setData({
text,
text: !isUsernameChar(text.slice(-1)) ? mentionTextToMarkup(text, userByUsername) : text,
});
},
[setData],
[setData, userByUsername],
);
const handleFieldKeyDown = useCallback(