mirror of
https://github.com/element-hq/element-web
synced 2024-11-22 09:15:41 +03:00
Step 8.5: Move event rendering utilities
This commit is contained in:
parent
4144d0ba57
commit
cfbad115c7
5 changed files with 116 additions and 92 deletions
|
@ -50,7 +50,7 @@ import Spinner from "../views/elements/Spinner";
|
||||||
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
||||||
import EditorStateTransfer from "../../utils/EditorStateTransfer";
|
import EditorStateTransfer from "../../utils/EditorStateTransfer";
|
||||||
import { Action } from '../../dispatcher/actions';
|
import { Action } from '../../dispatcher/actions';
|
||||||
import { getEventDisplayInfo } from "../../utils/EventUtils";
|
import { getEventDisplayInfo } from "../../utils/EventRenderingUtils";
|
||||||
import { IReadReceiptInfo } from "../views/rooms/ReadReceiptMarker";
|
import { IReadReceiptInfo } from "../views/rooms/ReadReceiptMarker";
|
||||||
import { haveRendererForEvent } from "../../events/EventTileFactory";
|
import { haveRendererForEvent } from "../../events/EventTileFactory";
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ import TooltipButton from '../elements/TooltipButton';
|
||||||
import ReadReceiptMarker, { IReadReceiptInfo } from "./ReadReceiptMarker";
|
import ReadReceiptMarker, { IReadReceiptInfo } from "./ReadReceiptMarker";
|
||||||
import MessageActionBar from "../messages/MessageActionBar";
|
import MessageActionBar from "../messages/MessageActionBar";
|
||||||
import ReactionsRow from '../messages/ReactionsRow';
|
import ReactionsRow from '../messages/ReactionsRow';
|
||||||
import { getEventDisplayInfo } from '../../../utils/EventUtils';
|
import { getEventDisplayInfo } from '../../../utils/EventRenderingUtils';
|
||||||
import SettingsStore from "../../../settings/SettingsStore";
|
import SettingsStore from "../../../settings/SettingsStore";
|
||||||
import { showThread } from '../../../dispatcher/dispatch-actions/threads';
|
import { showThread } from '../../../dispatcher/dispatch-actions/threads';
|
||||||
import { MessagePreviewStore } from '../../../stores/room-list/MessagePreviewStore';
|
import { MessagePreviewStore } from '../../../stores/room-list/MessagePreviewStore';
|
||||||
|
|
|
@ -27,7 +27,8 @@ import { Action } from '../../../dispatcher/actions';
|
||||||
import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
|
import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
|
||||||
import SenderProfile from "../messages/SenderProfile";
|
import SenderProfile from "../messages/SenderProfile";
|
||||||
import MImageReplyBody from "../messages/MImageReplyBody";
|
import MImageReplyBody from "../messages/MImageReplyBody";
|
||||||
import { getEventDisplayInfo, isVoiceMessage } from '../../../utils/EventUtils';
|
import { isVoiceMessage } from '../../../utils/EventUtils';
|
||||||
|
import { getEventDisplayInfo } from "../../../utils/EventRenderingUtils";
|
||||||
import MFileBody from "../messages/MFileBody";
|
import MFileBody from "../messages/MFileBody";
|
||||||
import MVoiceMessageBody from "../messages/MVoiceMessageBody";
|
import MVoiceMessageBody from "../messages/MVoiceMessageBody";
|
||||||
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
|
||||||
|
|
112
src/utils/EventRenderingUtils.ts
Normal file
112
src/utils/EventRenderingUtils.ts
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
|
import { EventType, MsgType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
import { M_POLL_START } from "matrix-events-sdk";
|
||||||
|
import { M_LOCATION } from "matrix-js-sdk/src/@types/location";
|
||||||
|
|
||||||
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
|
import { haveRendererForEvent, JitsiEventFactory, JSONEventFactory, pickFactory } from "../events/EventTileFactory";
|
||||||
|
import { MatrixClientPeg } from "../MatrixClientPeg";
|
||||||
|
import { getMessageModerationState, MessageModerationState } from "./EventUtils";
|
||||||
|
|
||||||
|
export function getEventDisplayInfo(mxEvent: MatrixEvent, hideEvent?: boolean): {
|
||||||
|
isInfoMessage: boolean;
|
||||||
|
hasRenderer: boolean;
|
||||||
|
isBubbleMessage: boolean;
|
||||||
|
isLeftAlignedBubbleMessage: boolean;
|
||||||
|
noBubbleEvent: boolean;
|
||||||
|
isSeeingThroughMessageHiddenForModeration: boolean;
|
||||||
|
} {
|
||||||
|
const content = mxEvent.getContent();
|
||||||
|
const msgtype = content.msgtype;
|
||||||
|
const eventType = mxEvent.getType();
|
||||||
|
|
||||||
|
let isSeeingThroughMessageHiddenForModeration = false;
|
||||||
|
if (SettingsStore.getValue("feature_msc3531_hide_messages_pending_moderation")) {
|
||||||
|
switch (getMessageModerationState(mxEvent)) {
|
||||||
|
case MessageModerationState.VISIBLE_FOR_ALL:
|
||||||
|
case MessageModerationState.HIDDEN_TO_CURRENT_USER:
|
||||||
|
// Nothing specific to do here
|
||||||
|
break;
|
||||||
|
case MessageModerationState.SEE_THROUGH_FOR_CURRENT_USER:
|
||||||
|
// Show message with a marker.
|
||||||
|
isSeeingThroughMessageHiddenForModeration = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Thread a MatrixClient through to here
|
||||||
|
let factory = pickFactory(mxEvent, MatrixClientPeg.get());
|
||||||
|
|
||||||
|
// Info messages are basically information about commands processed on a room
|
||||||
|
let isBubbleMessage = (
|
||||||
|
eventType.startsWith("m.key.verification") ||
|
||||||
|
(eventType === EventType.RoomMessage && msgtype?.startsWith("m.key.verification")) ||
|
||||||
|
(eventType === EventType.RoomCreate) ||
|
||||||
|
(eventType === EventType.RoomEncryption) ||
|
||||||
|
(factory === JitsiEventFactory)
|
||||||
|
);
|
||||||
|
const isLeftAlignedBubbleMessage = (
|
||||||
|
!isBubbleMessage &&
|
||||||
|
eventType === EventType.CallInvite
|
||||||
|
);
|
||||||
|
let isInfoMessage = (
|
||||||
|
!isBubbleMessage &&
|
||||||
|
!isLeftAlignedBubbleMessage &&
|
||||||
|
eventType !== EventType.RoomMessage &&
|
||||||
|
eventType !== EventType.RoomMessageEncrypted &&
|
||||||
|
eventType !== EventType.Sticker &&
|
||||||
|
eventType !== EventType.RoomCreate &&
|
||||||
|
!M_POLL_START.matches(eventType)
|
||||||
|
);
|
||||||
|
// Some non-info messages want to be rendered in the appropriate bubble column but without the bubble background
|
||||||
|
const noBubbleEvent = (
|
||||||
|
(eventType === EventType.RoomMessage && msgtype === MsgType.Emote) ||
|
||||||
|
M_POLL_START.matches(eventType) ||
|
||||||
|
M_LOCATION.matches(eventType) ||
|
||||||
|
(
|
||||||
|
eventType === EventType.RoomMessage &&
|
||||||
|
M_LOCATION.matches(msgtype)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// If we're showing hidden events in the timeline, we should use the
|
||||||
|
// source tile when there's no regular tile for an event and also for
|
||||||
|
// replace relations (which otherwise would display as a confusing
|
||||||
|
// duplicate of the thing they are replacing).
|
||||||
|
if (hideEvent || !haveRendererForEvent(mxEvent)) {
|
||||||
|
// forcefully ask for a factory for a hidden event (hidden event
|
||||||
|
// setting is checked internally)
|
||||||
|
// TODO: Thread a MatrixClient through to here
|
||||||
|
factory = pickFactory(mxEvent, MatrixClientPeg.get(), true);
|
||||||
|
if (factory === JSONEventFactory) {
|
||||||
|
isBubbleMessage = false;
|
||||||
|
// Reuse info message avatar and sender profile styling
|
||||||
|
isInfoMessage = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
hasRenderer: !!factory,
|
||||||
|
isInfoMessage,
|
||||||
|
isBubbleMessage,
|
||||||
|
isLeftAlignedBubbleMessage,
|
||||||
|
noBubbleEvent,
|
||||||
|
isSeeingThroughMessageHiddenForModeration,
|
||||||
|
};
|
||||||
|
}
|
|
@ -18,7 +18,6 @@ import { EventStatus, MatrixEvent } from 'matrix-js-sdk/src/models/event';
|
||||||
import { EventType, EVENT_VISIBILITY_CHANGE_TYPE, MsgType, RelationType } from "matrix-js-sdk/src/@types/event";
|
import { EventType, EVENT_VISIBILITY_CHANGE_TYPE, MsgType, RelationType } from "matrix-js-sdk/src/@types/event";
|
||||||
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
import { MatrixClient } from 'matrix-js-sdk/src/client';
|
||||||
import { logger } from 'matrix-js-sdk/src/logger';
|
import { logger } from 'matrix-js-sdk/src/logger';
|
||||||
import { M_LOCATION } from 'matrix-js-sdk/src/@types/location';
|
|
||||||
import { M_POLL_START } from "matrix-events-sdk";
|
import { M_POLL_START } from "matrix-events-sdk";
|
||||||
|
|
||||||
import { MatrixClientPeg } from '../MatrixClientPeg';
|
import { MatrixClientPeg } from '../MatrixClientPeg';
|
||||||
|
@ -29,7 +28,6 @@ import defaultDispatcher from "../dispatcher/dispatcher";
|
||||||
import { TimelineRenderingType } from "../contexts/RoomContext";
|
import { TimelineRenderingType } from "../contexts/RoomContext";
|
||||||
import { launchPollEditor } from "../components/views/messages/MPollBody";
|
import { launchPollEditor } from "../components/views/messages/MPollBody";
|
||||||
import { Action } from "../dispatcher/actions";
|
import { Action } from "../dispatcher/actions";
|
||||||
import { haveRendererForEvent, JitsiEventFactory, JSONEventFactory, pickFactory } from "../events/EventTileFactory";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether an event should allow actions like reply, reactions, edit, etc.
|
* Returns whether an event should allow actions like reply, reactions, edit, etc.
|
||||||
|
@ -196,93 +194,6 @@ export function getMessageModerationState(mxEvent: MatrixEvent, client?: MatrixC
|
||||||
return MessageModerationState.HIDDEN_TO_CURRENT_USER;
|
return MessageModerationState.HIDDEN_TO_CURRENT_USER;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEventDisplayInfo(mxEvent: MatrixEvent, hideEvent?: boolean): {
|
|
||||||
isInfoMessage: boolean;
|
|
||||||
hasRenderer: boolean;
|
|
||||||
isBubbleMessage: boolean;
|
|
||||||
isLeftAlignedBubbleMessage: boolean;
|
|
||||||
noBubbleEvent: boolean;
|
|
||||||
isSeeingThroughMessageHiddenForModeration: boolean;
|
|
||||||
} {
|
|
||||||
const content = mxEvent.getContent();
|
|
||||||
const msgtype = content.msgtype;
|
|
||||||
const eventType = mxEvent.getType();
|
|
||||||
|
|
||||||
let isSeeingThroughMessageHiddenForModeration = false;
|
|
||||||
if (SettingsStore.getValue("feature_msc3531_hide_messages_pending_moderation")) {
|
|
||||||
switch (getMessageModerationState(mxEvent)) {
|
|
||||||
case MessageModerationState.VISIBLE_FOR_ALL:
|
|
||||||
case MessageModerationState.HIDDEN_TO_CURRENT_USER:
|
|
||||||
// Nothing specific to do here
|
|
||||||
break;
|
|
||||||
case MessageModerationState.SEE_THROUGH_FOR_CURRENT_USER:
|
|
||||||
// Show message with a marker.
|
|
||||||
isSeeingThroughMessageHiddenForModeration = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Thread a MatrixClient through to here
|
|
||||||
let factory = pickFactory(mxEvent, MatrixClientPeg.get());
|
|
||||||
|
|
||||||
// Info messages are basically information about commands processed on a room
|
|
||||||
let isBubbleMessage = (
|
|
||||||
eventType.startsWith("m.key.verification") ||
|
|
||||||
(eventType === EventType.RoomMessage && msgtype?.startsWith("m.key.verification")) ||
|
|
||||||
(eventType === EventType.RoomCreate) ||
|
|
||||||
(eventType === EventType.RoomEncryption) ||
|
|
||||||
(factory === JitsiEventFactory)
|
|
||||||
);
|
|
||||||
const isLeftAlignedBubbleMessage = (
|
|
||||||
!isBubbleMessage &&
|
|
||||||
eventType === EventType.CallInvite
|
|
||||||
);
|
|
||||||
let isInfoMessage = (
|
|
||||||
!isBubbleMessage &&
|
|
||||||
!isLeftAlignedBubbleMessage &&
|
|
||||||
eventType !== EventType.RoomMessage &&
|
|
||||||
eventType !== EventType.RoomMessageEncrypted &&
|
|
||||||
eventType !== EventType.Sticker &&
|
|
||||||
eventType !== EventType.RoomCreate &&
|
|
||||||
!M_POLL_START.matches(eventType)
|
|
||||||
);
|
|
||||||
// Some non-info messages want to be rendered in the appropriate bubble column but without the bubble background
|
|
||||||
const noBubbleEvent = (
|
|
||||||
(eventType === EventType.RoomMessage && msgtype === MsgType.Emote) ||
|
|
||||||
M_POLL_START.matches(eventType) ||
|
|
||||||
M_LOCATION.matches(eventType) ||
|
|
||||||
(
|
|
||||||
eventType === EventType.RoomMessage &&
|
|
||||||
M_LOCATION.matches(msgtype)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// If we're showing hidden events in the timeline, we should use the
|
|
||||||
// source tile when there's no regular tile for an event and also for
|
|
||||||
// replace relations (which otherwise would display as a confusing
|
|
||||||
// duplicate of the thing they are replacing).
|
|
||||||
if (hideEvent || !haveRendererForEvent(mxEvent)) {
|
|
||||||
// forcefully ask for a factory for a hidden event (hidden event
|
|
||||||
// setting is checked internally)
|
|
||||||
// TODO: Thread a MatrixClient through to here
|
|
||||||
factory = pickFactory(mxEvent, MatrixClientPeg.get(), true);
|
|
||||||
if (factory === JSONEventFactory) {
|
|
||||||
isBubbleMessage = false;
|
|
||||||
// Reuse info message avatar and sender profile styling
|
|
||||||
isInfoMessage = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
hasRenderer: !!factory,
|
|
||||||
isInfoMessage,
|
|
||||||
isBubbleMessage,
|
|
||||||
isLeftAlignedBubbleMessage,
|
|
||||||
noBubbleEvent,
|
|
||||||
isSeeingThroughMessageHiddenForModeration,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isVoiceMessage(mxEvent: MatrixEvent): boolean {
|
export function isVoiceMessage(mxEvent: MatrixEvent): boolean {
|
||||||
const content = mxEvent.getContent();
|
const content = mxEvent.getContent();
|
||||||
// MSC2516 is a legacy identifier. See https://github.com/matrix-org/matrix-doc/pull/3245
|
// MSC2516 is a legacy identifier. See https://github.com/matrix-org/matrix-doc/pull/3245
|
||||||
|
|
Loading…
Reference in a new issue