Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Revert "Mentions as links rte (#10422)" #10458

Merged
merged 1 commit into from
Mar 27, 2023
Merged
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"dependencies": {
"@babel/runtime": "^7.12.5",
"@matrix-org/analytics-events": "^0.5.0",
"@matrix-org/matrix-wysiwyg": "^1.4.0",
"@matrix-org/matrix-wysiwyg": "^1.1.1",
"@matrix-org/react-sdk-module-api": "^0.0.4",
"@sentry/browser": "^7.0.0",
"@sentry/tracing": "^7.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,3 @@ limitations under the License.
border-color: $quaternary-content;
}
}

.mx_SendWysiwygComposer_AutoCompleteWrapper {
position: relative;
> .mx_Autocomplete {
min-width: 100%;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,6 @@ limitations under the License.
padding: unset;
}
}

/* this selector represents what will become a pill */
a[data-mention-type] {
cursor: text;
}
}

.mx_WysiwygComposer_Editor_content_placeholder::before {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, { memo, MutableRefObject, ReactNode, useEffect, useRef } from "react";
import React, { memo, MutableRefObject, ReactNode, useEffect } from "react";
import { useWysiwyg, FormattingFunctions } from "@matrix-org/matrix-wysiwyg";
import classNames from "classnames";

import Autocomplete from "../../Autocomplete";
import { WysiwygAutocomplete } from "./WysiwygAutocomplete";
import { FormattingButtons } from "./FormattingButtons";
import { Editor } from "./Editor";
import { useInputEventProcessor } from "../hooks/useInputEventProcessor";
import { useSetCursorPosition } from "../hooks/useSetCursorPosition";
import { useIsFocused } from "../hooks/useIsFocused";
import { useRoomContext } from "../../../../../contexts/RoomContext";
import defaultDispatcher from "../../../../../dispatcher/dispatcher";
import { Action } from "../../../../../dispatcher/actions";
import { parsePermalink } from "../../../../../utils/permalinks/Permalinks";

interface WysiwygComposerProps {
disabled?: boolean;
Expand All @@ -53,53 +47,21 @@ export const WysiwygComposer = memo(function WysiwygComposer({
rightComponent,
children,
}: WysiwygComposerProps) {
const { room } = useRoomContext();
const autocompleteRef = useRef<Autocomplete | null>(null);
const inputEventProcessor = useInputEventProcessor(onSend, initialContent);

const inputEventProcessor = useInputEventProcessor(onSend, autocompleteRef, initialContent);
const { ref, isWysiwygReady, content, actionStates, wysiwyg, suggestion } = useWysiwyg({
initialContent,
inputEventProcessor,
});
const { isFocused, onFocus } = useIsFocused();

const isReady = isWysiwygReady && !disabled;
const computedPlaceholder = (!content && placeholder) || undefined;

useSetCursorPosition(!isReady, ref);
const { ref, isWysiwygReady, content, actionStates, wysiwyg } = useWysiwyg({ initialContent, inputEventProcessor });

useEffect(() => {
if (!disabled && content !== null) {
onChange?.(content);
}
}, [onChange, content, disabled]);

useEffect(() => {
function handleClick(e: Event): void {
e.preventDefault();
if (
e.target &&
e.target instanceof HTMLAnchorElement &&
e.target.getAttribute("data-mention-type") === "user"
) {
const parsedLink = parsePermalink(e.target.href);
if (room && parsedLink?.userId)
defaultDispatcher.dispatch({
action: Action.ViewUser,
member: room.getMember(parsedLink.userId),
});
}
}

const mentions = ref.current?.querySelectorAll("a[data-mention-type]");
if (mentions) {
mentions.forEach((mention) => mention.addEventListener("click", handleClick));
}
const isReady = isWysiwygReady && !disabled;
useSetCursorPosition(!isReady, ref);

return () => {
if (mentions) mentions.forEach((mention) => mention.removeEventListener("click", handleClick));
};
}, [ref, room, content]);
const { isFocused, onFocus } = useIsFocused();
const computedPlaceholder = (!content && placeholder) || undefined;

return (
<div
Expand All @@ -108,7 +70,6 @@ export const WysiwygComposer = memo(function WysiwygComposer({
onFocus={onFocus}
onBlur={onFocus}
>
<WysiwygAutocomplete ref={autocompleteRef} suggestion={suggestion} handleMention={wysiwyg.mention} />
<FormattingButtons composer={wysiwyg} actionStates={actionStates} />
<Editor
ref={ref}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,9 @@ import { useMatrixClientContext } from "../../../../../contexts/MatrixClientCont
import { isCaretAtEnd, isCaretAtStart } from "../utils/selection";
import { getEventsFromEditorStateTransfer, getEventsFromRoom } from "../utils/event";
import { endEditing } from "../utils/editing";
import Autocomplete from "../../Autocomplete";

export function useInputEventProcessor(
onSend: () => void,
autocompleteRef: React.RefObject<Autocomplete>,
initialContent?: string,
): (event: WysiwygEvent, composer: Wysiwyg, editor: HTMLElement) => WysiwygEvent | null {
const roomContext = useRoomContext();
Expand All @@ -53,10 +51,6 @@ export function useInputEventProcessor(
const send = (): void => {
event.stopPropagation?.();
event.preventDefault?.();
// do not send the message if we have the autocomplete open, regardless of settings
if (autocompleteRef?.current && !autocompleteRef.current.state.hide) {
return;
}
onSend();
};

Expand All @@ -71,13 +65,12 @@ export function useInputEventProcessor(
roomContext,
composerContext,
mxClient,
autocompleteRef,
);
} else {
return handleInputEvent(event, send, isCtrlEnterToSend);
}
},
[isCtrlEnterToSend, onSend, initialContent, roomContext, composerContext, mxClient, autocompleteRef],
[isCtrlEnterToSend, onSend, initialContent, roomContext, composerContext, mxClient],
);
}

Expand All @@ -92,51 +85,12 @@ function handleKeyboardEvent(
roomContext: IRoomState,
composerContext: ComposerContextState,
mxClient: MatrixClient,
autocompleteRef: React.RefObject<Autocomplete>,
): KeyboardEvent | null {
const { editorStateTransfer } = composerContext;
const isEditing = Boolean(editorStateTransfer);
const isEditorModified = isEditing ? initialContent !== composer.content() : composer.content().length !== 0;
const action = getKeyBindingsManager().getMessageComposerAction(event);

const autocompleteIsOpen = autocompleteRef?.current && !autocompleteRef.current.state.hide;

// we need autocomplete to take priority when it is open for using enter to select
if (autocompleteIsOpen) {
let handled = false;
const autocompleteAction = getKeyBindingsManager().getAutocompleteAction(event);
const component = autocompleteRef.current;
if (component && component.countCompletions() > 0) {
switch (autocompleteAction) {
case KeyBindingAction.ForceCompleteAutocomplete:
case KeyBindingAction.CompleteAutocomplete:
autocompleteRef.current.onConfirmCompletion();
handled = true;
break;
case KeyBindingAction.PrevSelectionInAutocomplete:
autocompleteRef.current.moveSelection(-1);
handled = true;
break;
case KeyBindingAction.NextSelectionInAutocomplete:
autocompleteRef.current.moveSelection(1);
handled = true;
break;
case KeyBindingAction.CancelAutocomplete:
autocompleteRef.current.onEscape(event as {} as React.KeyboardEvent);
handled = true;
break;
default:
break; // don't return anything, allow event to pass through
}
}

if (handled) {
event.preventDefault();
event.stopPropagation();
return event;
}
}

switch (action) {
case KeyBindingAction.SendMessage:
send();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ describe("SendWysiwygComposer", () => {
customRender(jest.fn(), jest.fn(), false, true);

// Then
expect(await screen.findByTestId("WysiwygComposer")).toBeInTheDocument();
await waitFor(() => expect(screen.getByTestId("WysiwygComposer")).toBeTruthy());
});

it("Should render PlainTextComposer when isRichTextEnabled is at false", async () => {
it("Should render PlainTextComposer when isRichTextEnabled is at false", () => {
// When
customRender(jest.fn(), jest.fn(), false, false);

// Then
expect(await screen.findByTestId("PlainTextComposer")).toBeInTheDocument();
expect(screen.getByTestId("PlainTextComposer")).toBeTruthy();
});

describe.each([{ isRichTextEnabled: true }, { isRichTextEnabled: false }])(
Expand Down
Loading