Edit option (#1447)

* add func to parse html to editor input

* add  plain to html input function

* re-construct markdown

* fix missing return

* fix falsy condition

* fix reading href instead of src of emoji

* add message editor - WIP

* fix plain to editor input func

* add save edit message functionality

* show edited event source code

* focus message input on after editing message

* use del tag for strike-through instead of s

* prevent autocomplete from re-opening after esc

* scroll out of view msg editor in view

* handle up arrow edit

* handle scroll to message editor without effect

* revert prev commit: effect run after editor render

* ignore relation event from editable

* allow data-md tag for del and em in sanitize html

* prevent edit without changes

* ignore previous reply when replying to msg

* fix up arrow edit not working sometime
This commit is contained in:
Ajay Bura
2023-10-14 16:08:43 +11:00
committed by GitHub
parent 152576e85d
commit f5bcc9b851
18 changed files with 957 additions and 108 deletions

View File

@@ -12,7 +12,7 @@ import { useAtom } from 'jotai';
import isHotkey from 'is-hotkey';
import { EventType, IContent, MsgType, Room } from 'matrix-js-sdk';
import { ReactEditor } from 'slate-react';
import { Transforms, Range, Editor, Element } from 'slate';
import { Transforms, Range, Editor } from 'slate';
import {
Box,
Dialog,
@@ -51,6 +51,7 @@ import {
resetEditorHistory,
customHtmlEqualsPlainText,
trimCustomHtml,
isEmptyEditor,
} from '../../components/editor';
import { EmojiBoard, EmojiBoardTab } from '../../components/emoji-board';
import { UseStateProvider } from '../../components/UseStateProvider';
@@ -95,7 +96,12 @@ import navigation from '../../../client/state/navigation';
import cons from '../../../client/state/cons';
import { MessageReply } from '../../molecules/message/Message';
import colorMXID from '../../../util/colorMXID';
import { parseReplyBody, parseReplyFormattedBody } from '../../utils/room';
import {
parseReplyBody,
parseReplyFormattedBody,
trimReplyFromBody,
trimReplyFromFormattedBody,
} from '../../utils/room';
import { sanitizeText } from '../../utils/sanitize';
import { useScreenSize } from '../../hooks/useScreenSize';
@@ -264,13 +270,15 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
let body = plainText;
let formattedBody = customHtml;
if (replyDraft) {
body = parseReplyBody(replyDraft.userId, replyDraft.userId) + body;
body = parseReplyBody(replyDraft.userId, trimReplyFromBody(replyDraft.body)) + body;
formattedBody =
parseReplyFormattedBody(
roomId,
replyDraft.userId,
replyDraft.eventId,
replyDraft.formattedBody ?? sanitizeText(replyDraft.body)
replyDraft.formattedBody
? trimReplyFromFormattedBody(replyDraft.formattedBody)
: sanitizeText(replyDraft.body)
) + formattedBody;
}
@@ -321,19 +329,25 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
[submit, editor, setReplyDraft]
);
const handleKeyUp: KeyboardEventHandler = useCallback(() => {
const firstChildren = editor.children[0];
if (firstChildren && Element.isElement(firstChildren)) {
const isEmpty = editor.children.length === 1 && Editor.isEmpty(editor, firstChildren);
sendTypingStatus(!isEmpty);
}
const handleKeyUp: KeyboardEventHandler = useCallback(
(evt) => {
if (isHotkey('escape', evt)) {
evt.preventDefault();
return;
}
const prevWordRange = getPrevWorldRange(editor);
const query = prevWordRange
? getAutocompleteQuery<AutocompletePrefix>(editor, prevWordRange, AUTOCOMPLETE_PREFIXES)
: undefined;
setAutocompleteQuery(query);
}, [editor, sendTypingStatus]);
sendTypingStatus(!isEmptyEditor(editor));
const prevWordRange = getPrevWorldRange(editor);
const query = prevWordRange
? getAutocompleteQuery<AutocompletePrefix>(editor, prevWordRange, AUTOCOMPLETE_PREFIXES)
: undefined;
setAutocompleteQuery(query);
},
[editor, sendTypingStatus]
);
const handleCloseAutocomplete = useCallback(() => setAutocompleteQuery(undefined), []);
const handleEmoticonSelect = (key: string, shortcode: string) => {
editor.insertNode(createEmoticonElement(key, shortcode));
@@ -419,7 +433,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
roomId={roomId}
editor={editor}
query={autocompleteQuery}
requestClose={() => setAutocompleteQuery(undefined)}
requestClose={handleCloseAutocomplete}
/>
)}
{autocompleteQuery?.prefix === AutocompletePrefix.UserMention && (
@@ -427,7 +441,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
roomId={roomId}
editor={editor}
query={autocompleteQuery}
requestClose={() => setAutocompleteQuery(undefined)}
requestClose={handleCloseAutocomplete}
/>
)}
{autocompleteQuery?.prefix === AutocompletePrefix.Emoticon && (
@@ -435,10 +449,11 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
imagePackRooms={imagePackRooms}
editor={editor}
query={autocompleteQuery}
requestClose={() => setAutocompleteQuery(undefined)}
requestClose={handleCloseAutocomplete}
/>
)}
<CustomEditor
editableName="RoomInput"
editor={editor}
placeholder="Send a message..."
onKeyDown={handleKeyDown}