Make shared-components tiles render identically outside Element Web - #4 (#33622)

* Use shared MessageTimestampView in edit history

* Move timestamp typography into shared component

* Updated snapshots

* Update comments after clean up

* Fixed sonar issue and added tests for improved coverage

* Fix Prettier issue

* Fix font-size on timestamps and toolbar button sizing

* Updated snapshots

* Updated Storybook screenshots

* Updated screenshots

* Clean up app/web unused/redundant styling for disambiguated profile

* Fix merge error

* Fixes after merge

* Fixes after merge
This commit is contained in:
rbondesson
2026-06-01 05:47:59 +00:00
committed by GitHub
parent 32b66747f4
commit fc23fcad47
16 changed files with 322 additions and 70 deletions
@@ -9,12 +9,12 @@ Please see LICENSE files in the repository root for full details.
import React, { createRef } from "react";
import { type EventStatus, type IContent, type MatrixEvent, MatrixEventEvent, MsgType } from "matrix-js-sdk/src/matrix";
import classNames from "classnames";
import { ActionBarView, EventContentBodyView } from "@element-hq/web-shared-components";
import { ActionBarView, EventContentBodyView, MessageTimestampView } from "@element-hq/web-shared-components";
import { EditHistoryActionBarViewModel } from "../../../viewmodels/message-body/EditHistoryActionBarViewModel";
import { EventContentBodyViewModel } from "../../../viewmodels/message-body/EventContentBodyViewModel";
import { MessageTimestampViewModel } from "../../../viewmodels/room/timeline/event-tile/timestamp/MessageTimestampViewModel";
import { editBodyDiffToHtml } from "../../../utils/MessageDiffUtils";
import { formatTime } from "../../../DateUtils";
import Modal from "../../../Modal";
import ConfirmAndWaitRedactDialog from "../dialogs/ConfirmAndWaitRedactDialog";
import ViewSource from "../../structures/ViewSource";
@@ -45,8 +45,9 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
declare public context: React.ContextType<typeof MatrixClientContext>;
private content = createRef<HTMLDivElement>();
private EventContentBodyViewModel: EventContentBodyViewModel;
private editHistoryActionBarViewModel: EditHistoryActionBarViewModel;
private readonly eventContentBodyViewModel: EventContentBodyViewModel;
private readonly editHistoryActionBarViewModel: EditHistoryActionBarViewModel;
private readonly messageTimestampViewModel: MessageTimestampViewModel;
public constructor(props: IProps, context: React.ContextType<typeof MatrixClientContext>) {
super(props, context);
@@ -60,7 +61,7 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
this.state = { canRedact, sendStatus: event.getAssociatedStatus() };
const mxEventContent = getReplacedContent(event);
this.EventContentBodyViewModel = new EventContentBodyViewModel({
this.eventContentBodyViewModel = new EventContentBodyViewModel({
mxEvent: event,
content: mxEventContent,
highlights: [],
@@ -72,6 +73,11 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
linkify: true,
client: cli,
});
this.messageTimestampViewModel = new MessageTimestampViewModel({
ts: event.getTs(),
showTwelveHour: props.isTwelveHour,
inhibitTooltip: true,
});
this.editHistoryActionBarViewModel = new EditHistoryActionBarViewModel({
canRemove: !props.mxEvent.isRedacted() && !props.isBaseEvent && canRedact,
@@ -84,7 +90,15 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
public componentDidUpdate(prevProps: IProps): void {
if (prevProps.mxEvent !== this.props.mxEvent) {
const mxEventContent = getReplacedContent(this.props.mxEvent);
this.EventContentBodyViewModel.setEventContent(this.props.mxEvent, mxEventContent);
this.eventContentBodyViewModel.setEventContent(this.props.mxEvent, mxEventContent);
}
if (prevProps.mxEvent !== this.props.mxEvent || prevProps.isTwelveHour !== this.props.isTwelveHour) {
this.messageTimestampViewModel.setProps({
ts: this.props.mxEvent.getTs(),
showTwelveHour: this.props.isTwelveHour,
inhibitTooltip: true,
});
}
this.editHistoryActionBarViewModel.setProps({
@@ -129,18 +143,12 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
public componentWillUnmount(): void {
const event = this.props.mxEvent;
event.localRedactionEvent()?.off(MatrixEventEvent.Status, this.onAssociatedStatusChanged);
this.EventContentBodyViewModel.dispose();
this.eventContentBodyViewModel.dispose();
this.editHistoryActionBarViewModel.dispose();
this.messageTimestampViewModel.dispose();
}
private renderActionBar(): React.ReactNode {
this.editHistoryActionBarViewModel.setProps({
canRemove: !this.props.mxEvent.isRedacted() && !this.props.isBaseEvent && this.state.canRedact,
showViewSource: SettingsStore.getValue("developerMode"),
onRemoveClick: this.onRedactClick,
onViewSourceClick: this.onViewSourceClick,
});
return (
<ActionBarView vm={this.editHistoryActionBarViewModel} className="mx_ThreadActionBar mx_HistoryActionBar" />
);
@@ -157,7 +165,7 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
if (this.props.previousEdit) {
contentElements = editBodyDiffToHtml(getReplacedContent(this.props.previousEdit), content);
} else {
contentElements = <EventContentBodyView vm={this.EventContentBodyViewModel} as="span" />;
contentElements = <EventContentBodyView vm={this.eventContentBodyViewModel} as="span" />;
}
if (mxEvent.getContent().msgtype === MsgType.Emote) {
const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender();
@@ -177,7 +185,6 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
}
}
const timestamp = formatTime(new Date(mxEvent.getTs()), this.props.isTwelveHour);
const isSending = ["sending", "queued", "encrypting"].includes(this.state.sendStatus!);
const classes = classNames("mx_EventTile", {
// Note: we keep the `sending` state class for tests, not for our styles
@@ -187,7 +194,7 @@ export default class EditHistoryMessage extends React.PureComponent<IProps, ISta
<li>
<div className={classes}>
<div className="mx_EventTile_line">
<span className="mx_MessageTimestamp">{timestamp}</span>
<MessageTimestampView vm={this.messageTimestampViewModel} className="mx_MessageTimestamp" />
{contentContainer}
{this.renderActionBar()}
</div>