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

Commit

Permalink
Merge branch 'develop' into rav/element-r/default-on
Browse files Browse the repository at this point in the history
  • Loading branch information
richvdh committed Feb 6, 2023
2 parents 8ed6bcd + 5ba8eca commit 91872ad
Show file tree
Hide file tree
Showing 18 changed files with 511 additions and 386 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ interface IProps {
* A message tile showing that this room was created as an upgrade of a previous
* room.
*/
export const RoomCreate: React.FC<IProps> = ({ mxEvent, timestamp }) => {
export const RoomPredecessorTile: React.FC<IProps> = ({ mxEvent, timestamp }) => {
const msc3946ProcessDynamicPredecessor = SettingsStore.getValue("feature_dynamic_room_predecessors");

// Note: we ask the room for its predecessor here, instead of directly using
Expand Down Expand Up @@ -74,13 +74,14 @@ export const RoomCreate: React.FC<IProps> = ({ mxEvent, timestamp }) => {

if (!roomContext.room || roomContext.room.roomId !== mxEvent.getRoomId()) {
logger.warn(
"RoomCreate unexpectedly used outside of the context of the room containing this m.room.create event.",
"RoomPredecessorTile unexpectedly used outside of the context of the" +
"room containing this m.room.create event.",
);
return <></>;
}

if (!predecessor) {
logger.warn("RoomCreate unexpectedly used in a room with no predecessor.");
logger.warn("RoomPredecessorTile unexpectedly used in a room with no predecessor.");
return <div />;
}

Expand Down
1 change: 1 addition & 0 deletions src/components/views/rooms/MessageComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ export class MessageComposer extends React.Component<IProps, IState> {
e2eStatus={this.props.e2eStatus}
menuPosition={menuPosition}
placeholder={this.renderPlaceholderText()}
eventRelation={this.props.relation}
/>
);
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/rooms/RoomPreviewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ const RoomPreviewCard: FC<IProps> = ({ room, onJoinButtonClicked, onRejectButton
joinButtons = (
<>
<AccessibleButton
kind="secondary"
kind="primary_outline"
onClick={() => {
setBusy(true);
onRejectButtonClicked();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ limitations under the License.
*/

import { createContext, useContext } from "react";
import { IEventRelation } from "matrix-js-sdk/src/matrix";

import { SubSelection } from "./types";
import EditorStateTransfer from "../../../../utils/EditorStateTransfer";
Expand All @@ -29,6 +30,7 @@ export function getDefaultContextValue(defaultValue?: Partial<ComposerContextSta
export interface ComposerContextState {
selection: SubSelection;
editorStateTransfer?: EditorStateTransfer;
eventRelation?: IEventRelation;
}

export const ComposerContext = createContext<ComposerContextState>(getDefaultContextValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ limitations under the License.
*/

import React, { ForwardedRef, forwardRef, MutableRefObject, useRef } from "react";
import { IEventRelation } from "matrix-js-sdk/src/models/event";

import { useWysiwygSendActionHandler } from "./hooks/useWysiwygSendActionHandler";
import { WysiwygComposer } from "./components/WysiwygComposer";
Expand Down Expand Up @@ -48,17 +49,19 @@ interface SendWysiwygComposerProps {
onChange: (content: string) => void;
onSend: () => void;
menuPosition: MenuProps;
eventRelation?: IEventRelation;
}

// Default needed for React.lazy
export default function SendWysiwygComposer({
isRichTextEnabled,
e2eStatus,
menuPosition,
eventRelation,
...props
}: SendWysiwygComposerProps): JSX.Element {
const Composer = isRichTextEnabled ? WysiwygComposer : PlainTextComposer;
const defaultContextValue = useRef(getDefaultContextValue());
const defaultContextValue = useRef(getDefaultContextValue({ eventRelation }));

return (
<ComposerContext.Provider value={defaultContextValue.current}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function getFormattedContent(editorStateTransfer: EditorStateTransfer): string {
);
}

function parseEditorStateTransfer(
export function parseEditorStateTransfer(
editorStateTransfer: EditorStateTransfer,
room: Room,
mxClient: MatrixClient,
Expand Down Expand Up @@ -64,7 +64,7 @@ function parseEditorStateTransfer(
// this.saveStoredEditorState();
}

export function useInitialContent(editorStateTransfer: EditorStateTransfer): string {
export function useInitialContent(editorStateTransfer: EditorStateTransfer): string | undefined {
const roomContext = useRoomContext();
const mxClient = useMatrixClientContext();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { ComposerContextState, useComposerContext } from "../ComposerContext";
import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
import { useMatrixClientContext } from "../../../../../contexts/MatrixClientContext";
import { isCaretAtEnd, isCaretAtStart } from "../utils/selection";
import { getEventsFromEditorStateTransfer } from "../utils/event";
import { getEventsFromEditorStateTransfer, getEventsFromRoom } from "../utils/event";
import { endEditing } from "../utils/editing";

export function useInputEventProcessor(
Expand Down Expand Up @@ -87,22 +87,30 @@ function handleKeyboardEvent(
mxClient: MatrixClient,
): KeyboardEvent | null {
const { editorStateTransfer } = composerContext;
const isEditorModified = initialContent !== composer.content();
const isEditing = Boolean(editorStateTransfer);
const isEditorModified = isEditing ? initialContent !== composer.content() : composer.content().length !== 0;
const action = getKeyBindingsManager().getMessageComposerAction(event);

switch (action) {
case KeyBindingAction.SendMessage:
send();
return null;
case KeyBindingAction.EditPrevMessage: {
// If not in edition
// Or if the caret is not at the beginning of the editor
// Or the editor is modified
if (!editorStateTransfer || !isCaretAtStart(editor) || isEditorModified) {
if (!isCaretAtStart(editor) || isEditorModified) {
break;
}

const isDispatched = dispatchEditEvent(event, false, editorStateTransfer, roomContext, mxClient);
const isDispatched = dispatchEditEvent(
event,
false,
editorStateTransfer,
composerContext,
roomContext,
mxClient,
);

if (isDispatched) {
return null;
}
Expand All @@ -117,7 +125,14 @@ function handleKeyboardEvent(
break;
}

const isDispatched = dispatchEditEvent(event, true, editorStateTransfer, roomContext, mxClient);
const isDispatched = dispatchEditEvent(
event,
true,
editorStateTransfer,
composerContext,
roomContext,
mxClient,
);
if (!isDispatched) {
endEditing(roomContext);
event.preventDefault();
Expand All @@ -134,19 +149,22 @@ function handleKeyboardEvent(
function dispatchEditEvent(
event: KeyboardEvent,
isForward: boolean,
editorStateTransfer: EditorStateTransfer,
editorStateTransfer: EditorStateTransfer | undefined,
composerContext: ComposerContextState,
roomContext: IRoomState,
mxClient: MatrixClient,
): boolean {
const foundEvents = getEventsFromEditorStateTransfer(editorStateTransfer, roomContext, mxClient);
const foundEvents = editorStateTransfer
? getEventsFromEditorStateTransfer(editorStateTransfer, roomContext, mxClient)
: getEventsFromRoom(composerContext, roomContext);
if (!foundEvents) {
return false;
}

const newEvent = findEditableEvent({
events: foundEvents,
isForward,
fromEventId: editorStateTransfer.getEvent().getId(),
fromEventId: editorStateTransfer?.getEvent().getId(),
});
if (newEvent) {
dis.dispatch({
Expand Down
13 changes: 13 additions & 0 deletions src/components/views/rooms/wysiwyg_composer/utils/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ limitations under the License.
*/

import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread";

import EditorStateTransfer from "../../../../../utils/EditorStateTransfer";
import { IRoomState } from "../../../../structures/RoomView";
import { ComposerContextState } from "../ComposerContext";

// From EditMessageComposer private get events(): MatrixEvent[]
export function getEventsFromEditorStateTransfer(
Expand All @@ -44,3 +46,14 @@ export function getEventsFromEditorStateTransfer(
const isInThread = Boolean(editorStateTransfer.getEvent().getThread());
return liveTimelineEvents.concat(isInThread ? [] : pendingEvents);
}

// From SendMessageComposer private onKeyDown = (event: KeyboardEvent): void
export function getEventsFromRoom(
composerContext: ComposerContextState,
roomContext: IRoomState,
): MatrixEvent[] | undefined {
const isReplyingToThread = composerContext.eventRelation?.key === THREAD_RELATION_TYPE.name;
return roomContext.liveTimeline
?.getEvents()
.concat(isReplyingToThread ? [] : roomContext.room?.getPendingEvents() || []);
}
10 changes: 8 additions & 2 deletions src/components/views/rooms/wysiwyg_composer/utils/selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,21 @@ export function isCaretAtStart(editor: HTMLElement): boolean {
const selection = document.getSelection();

// No selection or the caret is not at the beginning of the selected element
if (!selection || selection.anchorOffset !== 0) {
if (!selection) {
return false;
}

// When we are pressing keyboard up in an empty main composer, the selection is on the editor with an anchorOffset at O or 1 (yes, this is strange)
const isOnFirstElement = selection.anchorNode === editor && selection.anchorOffset <= 1;
if (isOnFirstElement) {
return true;
}

// In case of nested html elements (list, code blocks), we are going through all the first child
let child = editor.firstChild;
do {
if (child === selection.anchorNode) {
return true;
return selection.anchorOffset === 0;
}
} while ((child = child?.firstChild || null));

Expand Down
4 changes: 2 additions & 2 deletions src/events/EventTileFactory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import LegacyCallEvent from "../components/views/messages/LegacyCallEvent";
import { CallEvent } from "../components/views/messages/CallEvent";
import TextualEvent from "../components/views/messages/TextualEvent";
import EncryptionEvent from "../components/views/messages/EncryptionEvent";
import { RoomCreate } from "../components/views/messages/RoomCreate";
import { RoomPredecessorTile } from "../components/views/messages/RoomPredecessorTile";
import RoomAvatarEvent from "../components/views/messages/RoomAvatarEvent";
import { WIDGET_LAYOUT_EVENT_TYPE } from "../stores/widgets/WidgetLayoutStore";
import { ALL_RULE_TYPES } from "../mjolnir/BanList";
Expand Down Expand Up @@ -92,7 +92,7 @@ const HiddenEventFactory: Factory = (ref, props) => <HiddenBody ref={ref} {...pr
// These factories are exported for reference comparison against pickFactory()
export const JitsiEventFactory: Factory = (ref, props) => <MJitsiWidgetEvent ref={ref} {...props} />;
export const JSONEventFactory: Factory = (ref, props) => <ViewSourceEvent ref={ref} {...props} />;
export const RoomCreateEventFactory: Factory = (ref, props) => <RoomCreate {...props} />;
export const RoomCreateEventFactory: Factory = (_ref, props) => <RoomPredecessorTile {...props} />;

const EVENT_TILE_TYPES = new Map<string, Factory>([
[EventType.RoomMessage, MessageEventFactory], // note that verification requests are handled in pickFactory()
Expand Down
3 changes: 2 additions & 1 deletion src/rageshake/submit-rageshake.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ async function collectBugReport(opts: IOpts = {}, gzipLogs = true): Promise<Form
body.append("user_id", client.credentials.userId);
body.append("device_id", client.deviceId);

if (client.isCryptoEnabled()) {
// TODO: make this work with rust crypto
if (client.isCryptoEnabled() && client.crypto) {
const keys = [`ed25519:${client.getDeviceEd25519Key()}`];
if (client.getDeviceCurve25519Key) {
keys.push(`curve25519:${client.getDeviceCurve25519Key()}`);
Expand Down
3 changes: 2 additions & 1 deletion src/sentry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ function getEnabledLabs(): string {
}

async function getCryptoContext(client: MatrixClient): Promise<CryptoContext> {
if (!client.isCryptoEnabled()) {
// TODO: make this work with rust crypto
if (!client.isCryptoEnabled() || !client.crypto) {
return {};
}
const keys = [`ed25519:${client.getDeviceEd25519Key()}`];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { EventType, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";

import dis from "../../../../src/dispatcher/dispatcher";
import SettingsStore from "../../../../src/settings/SettingsStore";
import { RoomCreate } from "../../../../src/components/views/messages/RoomCreate";
import { RoomPredecessorTile } from "../../../../src/components/views/messages/RoomPredecessorTile";
import { stubClient, upsertRoomStateEvents } from "../../../test-utils/test-utils";
import { Action } from "../../../../src/dispatcher/actions";
import RoomContext from "../../../../src/contexts/RoomContext";
Expand All @@ -31,7 +31,7 @@ import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";

jest.mock("../../../../src/dispatcher/dispatcher");

describe("<RoomCreate />", () => {
describe("<RoomPredecessorTile />", () => {
const userId = "@alice:server.org";
const roomId = "!room:server.org";
const createEvent = new MatrixEvent({
Expand Down Expand Up @@ -97,34 +97,34 @@ describe("<RoomCreate />", () => {
jest.spyOn(SettingsStore, "setValue").mockRestore();
});

function renderRoomCreate(room: Room) {
function renderTile(room: Room) {
return render(
<RoomContext.Provider value={getRoomContext(room, {})}>
<RoomCreate mxEvent={createEvent} />
<RoomPredecessorTile mxEvent={createEvent} />
</RoomContext.Provider>,
);
}

it("Renders as expected", () => {
const roomCreate = renderRoomCreate(roomJustCreate);
const roomCreate = renderTile(roomJustCreate);
expect(roomCreate.asFragment()).toMatchSnapshot();
});

it("Links to the old version of the room", () => {
renderRoomCreate(roomJustCreate);
renderTile(roomJustCreate);
expect(screen.getByText("Click here to see older messages.")).toHaveAttribute(
"href",
"https://matrix.to/#/old_room_id/tombstone_event_id",
);
});

it("Shows an empty div if there is no predecessor", () => {
renderRoomCreate(roomNoPredecessors);
renderTile(roomNoPredecessors);
expect(screen.queryByText("Click here to see older messages.", { exact: false })).toBeNull();
});

it("Opens the old room on click", async () => {
renderRoomCreate(roomJustCreate);
renderTile(roomJustCreate);
const link = screen.getByText("Click here to see older messages.");

await act(() => userEvent.click(link));
Expand All @@ -142,7 +142,7 @@ describe("<RoomCreate />", () => {
});

it("Ignores m.predecessor if labs flag is off", () => {
renderRoomCreate(roomCreateAndPredecessor);
renderTile(roomCreateAndPredecessor);
expect(screen.getByText("Click here to see older messages.")).toHaveAttribute(
"href",
"https://matrix.to/#/old_room_id/tombstone_event_id",
Expand All @@ -161,23 +161,23 @@ describe("<RoomCreate />", () => {
});

it("Uses the create event if there is no m.predecessor", () => {
renderRoomCreate(roomJustCreate);
renderTile(roomJustCreate);
expect(screen.getByText("Click here to see older messages.")).toHaveAttribute(
"href",
"https://matrix.to/#/old_room_id/tombstone_event_id",
);
});

it("Uses m.predecessor when it's there", () => {
renderRoomCreate(roomCreateAndPredecessor);
renderTile(roomCreateAndPredecessor);
expect(screen.getByText("Click here to see older messages.")).toHaveAttribute(
"href",
"https://matrix.to/#/old_room_id_from_predecessor",
);
});

it("Links to the event in the room if event ID is provided", () => {
renderRoomCreate(roomCreateAndPredecessorWithEventId);
renderTile(roomCreateAndPredecessorWithEventId);
expect(screen.getByText("Click here to see older messages.")).toHaveAttribute(
"href",
"https://matrix.to/#/old_room_id_from_predecessor/tombstone_event_id_from_predecessor",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<RoomCreate /> Renders as expected 1`] = `
exports[`<RoomPredecessorTile /> Renders as expected 1`] = `
<DocumentFragment>
<div
class="mx_EventTileBubble mx_CreateEvent"
Expand Down
Loading

0 comments on commit 91872ad

Please sign in to comment.