Show a blue lock for unencrypted rooms and hide the grey shield for encrypted rooms (#30440)

* Show a blue lock instead of a grey shield for unencrypted rooms

* Update screenshots and snapshot

* Update snapshots and fix e2e test that used to expect the grey shield

* lint and add tests for shield

* Update more screen shots

* finish unit test for left icon

* Remove unneeded check

* Don't bother adding stray props to E2EIcon for data-testid

* Upate snapshots
This commit is contained in:
David Langley
2025-08-11 10:35:04 +01:00
committed by GitHub
parent 4da27eb199
commit 59531ea512
36 changed files with 128 additions and 19 deletions

View File

@@ -74,18 +74,18 @@ const E2EIcon: React.FC<Props> = ({
let content: JSX.Element;
if (onClick) {
content = <AccessibleButton onClick={onClick} className={classes} style={style} />;
content = <AccessibleButton onClick={onClick} className={classes} style={style} data-testid="e2e-icon" />;
} else {
// Verified and warning icon have a transparent cutout, so add a white background.
// The normal icon already has the correct shape and size, so reuse that.
if (status === E2EStatus.Verified || status === E2EStatus.Warning) {
content = (
<div className={classes} style={style}>
<div className={classes} style={style} data-testid="e2e-icon">
<div className="mx_E2EIcon_normal" />
</div>
);
} else {
content = <div className={classes} style={style} />;
content = <div className={classes} style={style} data-testid="e2e-icon" />;
}
}

View File

@@ -19,6 +19,7 @@ import {
import { type Optional } from "matrix-events-sdk";
import { Tooltip } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import { LockOffIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { _t } from "../../../languageHandler";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
@@ -36,7 +37,7 @@ import VoiceRecordComposerTile from "./VoiceRecordComposerTile";
import { VoiceRecordingStore } from "../../../stores/VoiceRecordingStore";
import { RecordingState } from "../../../audio/VoiceRecording";
import type ResizeNotifier from "../../../utils/ResizeNotifier";
import { type E2EStatus } from "../../../utils/ShieldUtils";
import { E2EStatus } from "../../../utils/ShieldUtils";
import SendMessageComposer, { type SendMessageComposer as SendMessageComposerClass } from "./SendMessageComposer";
import { type ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload";
import { Action } from "../../../dispatcher/actions";
@@ -525,12 +526,27 @@ export class MessageComposer extends React.Component<IProps, IState> {
};
public render(): React.ReactNode {
const hasE2EIcon = Boolean(!this.state.isWysiwygLabEnabled && this.props.e2eStatus);
const e2eIcon = hasE2EIcon && (
<div className="mx_MessageComposer_e2eIconWrapper">
<E2EIcon key="e2eIcon" status={this.props.e2eStatus!} className="mx_MessageComposer_e2eIcon" />
</div>
);
let leftIcon: false | JSX.Element = false;
if (!this.state.isWysiwygLabEnabled) {
if (!this.props.e2eStatus) {
leftIcon = (
<div className="mx_MessageComposer_e2eIconWrapper">
<LockOffIcon
width={12}
height={12}
color="var(--cpd-color-icon-info-primary)"
className="mx_E2EIcon mx_MessageComposer_e2eIcon"
/>
</div>
);
} else if (this.props.e2eStatus !== E2EStatus.Normal) {
leftIcon = (
<div className="mx_MessageComposer_e2eIconWrapper">
<E2EIcon key="e2eIcon" status={this.props.e2eStatus} className="mx_MessageComposer_e2eIcon" />
</div>
);
}
}
const controls: ReactNode[] = [];
const menuPosition = this.getMenuPosition();
@@ -640,7 +656,7 @@ export class MessageComposer extends React.Component<IProps, IState> {
const classes = classNames({
"mx_MessageComposer": true,
"mx_MessageComposer--compact": this.props.compact,
"mx_MessageComposer_e2eStatus": hasE2EIcon,
"mx_MessageComposer_e2eStatus": leftIcon,
"mx_MessageComposer_wysiwyg": this.state.isWysiwygLabEnabled,
});
@@ -654,7 +670,7 @@ export class MessageComposer extends React.Component<IProps, IState> {
permalinkCreator={this.props.permalinkCreator}
/>
<div className="mx_MessageComposer_row">
{e2eIcon}
{leftIcon}
{composer}
<div className="mx_MessageComposer_actions">
{controls}

View File

@@ -8,12 +8,13 @@ Please see LICENSE files in the repository root for full details.
import React, { type JSX, type RefObject, useMemo, type ReactNode } from "react";
import { type IEventRelation } from "matrix-js-sdk/src/matrix";
import LockOffIcon from "@vector-im/compound-design-tokens/assets/web/icons/lock-off";
import { useWysiwygSendActionHandler } from "./hooks/useWysiwygSendActionHandler";
import { WysiwygComposer } from "./components/WysiwygComposer";
import { PlainTextComposer } from "./components/PlainTextComposer";
import { type ComposerFunctions } from "./types";
import { type E2EStatus } from "../../../../utils/ShieldUtils";
import { E2EStatus } from "../../../../utils/ShieldUtils";
import E2EIcon from "../E2EIcon";
import { type MenuProps } from "../../../structures/ContextMenu";
import { Emoji } from "./components/Emoji";
@@ -55,11 +56,25 @@ export default function SendWysiwygComposer({
[props.eventRelation],
);
let leftIcon: false | JSX.Element = false;
if (!e2eStatus) {
leftIcon = (
<LockOffIcon
data-testid="e2e-icon"
width={12}
height={12}
color="var(--cpd-color-icon-info-primary)"
className="mx_E2EIcon"
/>
);
} else if (e2eStatus !== E2EStatus.Normal) {
leftIcon = <E2EIcon status={e2eStatus} />;
}
return (
<ComposerContext.Provider value={defaultContextValue}>
<Composer
className="mx_SendWysiwygComposer"
leftComponent={e2eStatus && <E2EIcon status={e2eStatus} />}
leftComponent={leftIcon}
rightComponent={<Emoji menuPosition={menuPosition} />}
{...props}
>