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
This commit is contained in:
@@ -84,4 +84,13 @@ export class DecryptionFailureBodyViewModel
|
||||
this.props.verificationState = verificationState;
|
||||
this.snapshot.merge({ isLocalDeviceVerified: verificationState });
|
||||
}
|
||||
|
||||
public setDecryptionFailureCode(decryptionFailureCode: DecryptionFailureCode | null): void {
|
||||
if (this.props.decryptionFailureCode === decryptionFailureCode) return;
|
||||
|
||||
this.props.decryptionFailureCode = decryptionFailureCode;
|
||||
this.snapshot.merge({
|
||||
decryptionFailureReason: DecryptionFailureBodyViewModel.getDecryptionReasonFromCode(decryptionFailureCode),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user