Files
ThreadNet-Web/apps/web/src/viewmodels/message-body/RedactedBodyViewModel.ts
T
ZackandGitHub 4f3a1a2cc6 Refactor and Move RedactedBodyView To Shared Components (#32772)
* refactoring and creation of shared-components for reductedBodyView

* move redacted message rendering to shared MVVM view

* Update snapshots + fix lint errors

* Remove MatrixClientPeg and use reguler react matrix client context

* Stop resyncing redacted body view models with mxEvent

* Fix redacted_because test fixtures for stricter event typing

* Simplify redacted body client access

* Watch timestamp setting in redacted body view model

* Refactor redacted and decryption failure body factories into MBodyFactory

* Prettier Fix

* Refactor FileBody into same pattern for consitancy
2026-03-24 10:02:07 +00:00

113 lines
3.9 KiB
TypeScript

/*
* Copyright 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
import { type MatrixEvent } from "matrix-js-sdk/src/matrix";
import {
BaseViewModel,
type RedactedBodyViewSnapshot,
type RedactedBodyViewModel as RedactedBodyViewModelInterface,
} from "@element-hq/web-shared-components";
import { formatFullDate } from "../../DateUtils";
import { _t } from "../../languageHandler";
import { MatrixClientPeg } from "../../MatrixClientPeg";
import SettingsStore from "../../settings/SettingsStore";
export interface RedactedBodyViewModelProps {
/**
* The redacted event being rendered.
*/
mxEvent: MatrixEvent;
}
export class RedactedBodyViewModel
extends BaseViewModel<RedactedBodyViewSnapshot, RedactedBodyViewModelProps>
implements RedactedBodyViewModelInterface
{
private showTwelveHour: boolean;
private static readonly computeText = ({ mxEvent }: RedactedBodyViewModelProps): string => {
const redactedBecauseUserId = mxEvent.getUnsigned().redacted_because?.sender;
if (!redactedBecauseUserId || redactedBecauseUserId === mxEvent.getSender()) {
return _t("timeline|self_redaction");
}
const roomId = mxEvent.getRoomId();
const room = roomId ? MatrixClientPeg.get()?.getRoom(roomId) : null;
const sender = room?.getMember(redactedBecauseUserId);
return _t("timeline|redaction", { name: sender?.name ?? redactedBecauseUserId });
};
private static readonly computeTooltip = (mxEvent: MatrixEvent, showTwelveHour: boolean): string | undefined => {
const redactionTs = mxEvent.getUnsigned().redacted_because?.origin_server_ts;
if (!redactionTs) {
return undefined;
}
return _t("timeline|redacted|tooltip", {
date: formatFullDate(new Date(redactionTs), showTwelveHour),
});
};
private static readonly computeSnapshot = (
props: RedactedBodyViewModelProps,
showTwelveHour: boolean,
): RedactedBodyViewSnapshot => ({
text: RedactedBodyViewModel.computeText(props),
tooltip: RedactedBodyViewModel.computeTooltip(props.mxEvent, showTwelveHour),
});
public constructor(props: RedactedBodyViewModelProps) {
const showTwelveHour = SettingsStore.getValue("showTwelveHourTimestamps");
super(props, RedactedBodyViewModel.computeSnapshot(props, showTwelveHour));
this.showTwelveHour = showTwelveHour;
const showTwelveHourWatcherRef = SettingsStore.watchSetting(
"showTwelveHourTimestamps",
null,
(_settingName, _roomId, _level, _newValAtLevel, newVal) => {
if (this.showTwelveHour === newVal) return;
this.showTwelveHour = newVal;
this.updateTooltip();
},
);
this.disposables.track(() => SettingsStore.unwatchSetting(showTwelveHourWatcherRef));
}
public setEvent(mxEvent: MatrixEvent): void {
if (this.props.mxEvent === mxEvent) return;
this.props = { ...this.props, mxEvent };
const text = RedactedBodyViewModel.computeText(this.props);
const tooltip = RedactedBodyViewModel.computeTooltip(this.props.mxEvent, this.showTwelveHour);
const updates: Partial<RedactedBodyViewSnapshot> = {};
if (this.snapshot.current.text !== text) {
updates.text = text;
}
if (this.snapshot.current.tooltip !== tooltip) {
updates.tooltip = tooltip;
}
if (Object.keys(updates).length > 0) {
this.snapshot.merge(updates);
}
}
private updateTooltip(): void {
const tooltip = RedactedBodyViewModel.computeTooltip(this.props.mxEvent, this.showTwelveHour);
if (this.snapshot.current.tooltip !== tooltip) {
this.snapshot.merge({ tooltip });
}
}
}