Files
blap/src/viewmodels/message-body/DecryptionFailureBodyViewModel.ts
T
rbondesson 25d24d478f Refactor DecryptionFailureBody using MVVM and move to shared-components (#31829)
* Refactor DecryptionFailureBody to MVVM and moving it to shared components

* Added unit test for DecryptionFailureBodyViewModel

* Removing the dependency to matrix.js-sdk from the shared component

* Kepp class mx_EventTile_content for tile layout

* Required changes after rebase

* Updates after PR review requests

* Clean up unused translation tags in element-web

* Added missing unit tests to improve coverage

* Additional unit tests to improve test coverage

* Removing obsolete tests from the snap

* Only listen to verification state changes in the wrapper components and also limit the view model to only allow updates in verification state.

* Updates after review requests

* Updated and added missing playwright snapshots

* Bettter structure on view model

---------

Co-authored-by: Florian Duros <florianduros@element.io>
Co-authored-by: Zack <zazi21@student.bth.se>
2026-01-30 12:44:23 +00:00

101 lines
4.2 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 { DecryptionFailureCode } from "matrix-js-sdk/src/crypto-api";
import {
BaseViewModel,
DecryptionFailureReason,
type DecryptionFailureBodyViewSnapshot as DecryptionFailureBodyViewSnapshotInterface,
type DecryptionFailureBodyViewModel as DecryptionFailureBodyViewModelInterface,
} from "@element-hq/web-shared-components";
export interface DecryptionFailureBodyViewModelProps {
/**
* The message event being rendered.
*/
decryptionFailureCode: DecryptionFailureCode | null;
/**
* The local device verification state.
*/
verificationState?: boolean;
/**
* Extra CSS classes to apply to the component
*/
extraClassNames?: string[];
}
/**
* ViewModel for the decryption failure body, providing the current state of the component.
*/
export class DecryptionFailureBodyViewModel
extends BaseViewModel<DecryptionFailureBodyViewSnapshotInterface, DecryptionFailureBodyViewModelProps>
implements DecryptionFailureBodyViewModelInterface
{
/**
* Convert enum DecryptionFailureCode to enum DecryptionFailureReason.
*/
private static getDecryptionReasonFromCode(
decryptionFailureCode: DecryptionFailureCode | null,
): DecryptionFailureReason {
switch (decryptionFailureCode) {
case DecryptionFailureCode.HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED:
return DecryptionFailureReason.HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED;
case DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP:
return DecryptionFailureReason.HISTORICAL_MESSAGE_NO_KEY_BACKUP;
case DecryptionFailureCode.HISTORICAL_MESSAGE_USER_NOT_JOINED:
return DecryptionFailureReason.HISTORICAL_MESSAGE_USER_NOT_JOINED;
case DecryptionFailureCode.MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE:
return DecryptionFailureReason.MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE;
case DecryptionFailureCode.SENDER_IDENTITY_PREVIOUSLY_VERIFIED:
return DecryptionFailureReason.SENDER_IDENTITY_PREVIOUSLY_VERIFIED;
case DecryptionFailureCode.UNSIGNED_SENDER_DEVICE:
return DecryptionFailureReason.UNSIGNED_SENDER_DEVICE;
default:
return DecryptionFailureReason.UNABLE_TO_DECRYPT;
}
}
/**
* @param decryptionFailureCode - The decryption failure code for the event.
* @param verificationState - The local device verification state.
* @param extraClassNames - Extra CSS classes to apply to the component.
*/
private static readonly computeSnapshot = (
decryptionFailureCode: DecryptionFailureCode | null,
verificationState?: boolean,
extraClassNames?: string[],
): DecryptionFailureBodyViewSnapshotInterface => {
// Keep mx_DecryptionFailureBody and mx_EventTile_content to support the compatibility with existing timeline and the all the layout
const defaultClassNames = ["mx_DecryptionFailureBody", "mx_EventTile_content"];
return {
decryptionFailureReason: DecryptionFailureBodyViewModel.getDecryptionReasonFromCode(decryptionFailureCode),
isLocalDeviceVerified: verificationState,
extraClassNames: extraClassNames ? defaultClassNames.concat(extraClassNames) : defaultClassNames,
};
};
public constructor(props: DecryptionFailureBodyViewModelProps) {
super(
props,
DecryptionFailureBodyViewModel.computeSnapshot(
props.decryptionFailureCode,
props.verificationState,
props.extraClassNames,
),
);
}
/**
* Updates the properties of the view model and recomputes the snapshot.
* @param verificationState - The updated local device verification state.
*/
public setVerificationState(verificationState?: boolean): void {
this.props.verificationState = verificationState;
this.snapshot.merge({ isLocalDeviceVerified: verificationState });
}
}