Task - replace img icons with svg components (#8963)
* add role=presentation to backdrop panle image * replace img icons with svg components in InviteDialog * replace img icon with svg component * img icons to svg icons in MImageBody * remove log * img icon to svg in SecurityRoomSettingsTab * use shared error message for media message tiles * remove nbsp * dont snapshot test entire rtl render response * use aria-describedby for uploadconfirm preview * use aria-labelledby instead
This commit is contained in:
parent
afa8b01601
commit
7afc8c5869
13 changed files with 135 additions and 23 deletions
|
@ -26,6 +26,7 @@
|
||||||
@import "./components/views/location/_ShareType.scss";
|
@import "./components/views/location/_ShareType.scss";
|
||||||
@import "./components/views/location/_ZoomButtons.scss";
|
@import "./components/views/location/_ZoomButtons.scss";
|
||||||
@import "./components/views/messages/_MBeaconBody.scss";
|
@import "./components/views/messages/_MBeaconBody.scss";
|
||||||
|
@import "./components/views/messages/shared/_MediaProcessingError.scss";
|
||||||
@import "./components/views/spaces/_QuickThemeSwitcher.scss";
|
@import "./components/views/spaces/_QuickThemeSwitcher.scss";
|
||||||
@import "./structures/_AutoHideScrollbar.scss";
|
@import "./structures/_AutoHideScrollbar.scss";
|
||||||
@import "./structures/_BackdropPanel.scss";
|
@import "./structures/_BackdropPanel.scss";
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_MediaProcessingError_Icon {
|
||||||
|
margin-right: $spacing-4;
|
||||||
|
vertical-align: text-top;
|
||||||
|
}
|
|
@ -36,6 +36,8 @@ export const BackdropPanel: React.FC<IProps> = ({ backgroundImage, blurMultiplie
|
||||||
}
|
}
|
||||||
return <div className="mx_BackdropPanel">
|
return <div className="mx_BackdropPanel">
|
||||||
<img
|
<img
|
||||||
|
role="presentation"
|
||||||
|
alt=""
|
||||||
style={styles}
|
style={styles}
|
||||||
className="mx_BackdropPanel--image"
|
className="mx_BackdropPanel--image"
|
||||||
src={backgroundImage} />
|
src={backgroundImage} />
|
||||||
|
|
|
@ -21,6 +21,8 @@ import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
|
import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call';
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
import { Icon as InfoIcon } from "../../../../res/img/element-icons/info.svg";
|
||||||
|
import { Icon as EmailPillAvatarIcon } from "../../../../res/img/icon-email-pill-avatar.svg";
|
||||||
import { _t, _td } from "../../../languageHandler";
|
import { _t, _td } from "../../../languageHandler";
|
||||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||||
import { makeRoomPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
|
import { makeRoomPermalink, makeUserPermalink } from "../../../utils/permalinks/Permalinks";
|
||||||
|
@ -186,8 +188,7 @@ class DMRoomTile extends React.PureComponent<IDMRoomTileProps> {
|
||||||
|
|
||||||
const avatarSize = 36;
|
const avatarSize = 36;
|
||||||
const avatar = (this.props.member as ThreepidMember).isEmail
|
const avatar = (this.props.member as ThreepidMember).isEmail
|
||||||
? <img
|
? <EmailPillAvatarIcon
|
||||||
src={require("../../../../res/img/icon-email-pill-avatar.svg").default}
|
|
||||||
width={avatarSize}
|
width={avatarSize}
|
||||||
height={avatarSize}
|
height={avatarSize}
|
||||||
/>
|
/>
|
||||||
|
@ -1152,10 +1153,7 @@ export default class InviteDialog extends React.PureComponent<IInviteDialogProps
|
||||||
if (visibility === "world_readable" || visibility === "shared") {
|
if (visibility === "world_readable" || visibility === "shared") {
|
||||||
keySharingWarning =
|
keySharingWarning =
|
||||||
<p className='mx_InviteDialog_helpText'>
|
<p className='mx_InviteDialog_helpText'>
|
||||||
<img
|
<InfoIcon height={14} width={14} />
|
||||||
src={require("../../../../res/img/element-icons/info.svg").default}
|
|
||||||
width={14}
|
|
||||||
height={14} />
|
|
||||||
{ " " + _t("Invited people will be able to read old messages.") }
|
{ " " + _t("Invited people will be able to read old messages.") }
|
||||||
</p>;
|
</p>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import filesize from "filesize";
|
import filesize from "filesize";
|
||||||
|
|
||||||
|
import { Icon as FileIcon } from '../../../../res/img/feather-customised/files.svg';
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import { getBlobSafeMimeType } from '../../../utils/blobs';
|
import { getBlobSafeMimeType } from '../../../utils/blobs';
|
||||||
import BaseDialog from "./BaseDialog";
|
import BaseDialog from "./BaseDialog";
|
||||||
|
@ -80,11 +81,16 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
|
||||||
title = _t('Upload files');
|
title = _t('Upload files');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fileId = `mx-uploadconfirmdialog-${this.props.file.name}`;
|
||||||
let preview: JSX.Element;
|
let preview: JSX.Element;
|
||||||
let placeholder: JSX.Element;
|
let placeholder: JSX.Element;
|
||||||
if (this.mimeType.startsWith("image/")) {
|
if (this.mimeType.startsWith("image/")) {
|
||||||
preview = (
|
preview = (
|
||||||
<img className="mx_UploadConfirmDialog_imagePreview" src={this.objectUrl} />
|
<img
|
||||||
|
className="mx_UploadConfirmDialog_imagePreview"
|
||||||
|
src={this.objectUrl}
|
||||||
|
aria-labelledby={fileId}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
} else if (this.mimeType.startsWith("video/")) {
|
} else if (this.mimeType.startsWith("video/")) {
|
||||||
preview = (
|
preview = (
|
||||||
|
@ -92,9 +98,10 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
placeholder = (
|
placeholder = (
|
||||||
<img
|
<FileIcon
|
||||||
className="mx_UploadConfirmDialog_fileIcon"
|
className="mx_UploadConfirmDialog_fileIcon"
|
||||||
src={require("../../../../res/img/feather-customised/files.svg").default}
|
height={18}
|
||||||
|
width={18}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +125,7 @@ export default class UploadConfirmDialog extends React.Component<IProps> {
|
||||||
<div className="mx_UploadConfirmDialog_previewOuter">
|
<div className="mx_UploadConfirmDialog_previewOuter">
|
||||||
<div className="mx_UploadConfirmDialog_previewInner">
|
<div className="mx_UploadConfirmDialog_previewInner">
|
||||||
{ preview && <div>{ preview }</div> }
|
{ preview && <div>{ preview }</div> }
|
||||||
<div>
|
<div id={fileId}>
|
||||||
{ placeholder }
|
{ placeholder }
|
||||||
{ this.props.file.name } ({ filesize(this.props.file.size) })
|
{ this.props.file.name } ({ filesize(this.props.file.size) })
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,6 +28,7 @@ import { PlaybackManager } from "../../../audio/PlaybackManager";
|
||||||
import { isVoiceMessage } from "../../../utils/EventUtils";
|
import { isVoiceMessage } from "../../../utils/EventUtils";
|
||||||
import { PlaybackQueue } from "../../../audio/PlaybackQueue";
|
import { PlaybackQueue } from "../../../audio/PlaybackQueue";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
||||||
|
import MediaProcessingError from "./shared/MediaProcessingError";
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
error?: Error;
|
error?: Error;
|
||||||
|
@ -93,10 +94,9 @@ export default class MAudioBody extends React.PureComponent<IBodyProps, IState>
|
||||||
public render() {
|
public render() {
|
||||||
if (this.state.error) {
|
if (this.state.error) {
|
||||||
return (
|
return (
|
||||||
<span className="mx_MAudioBody">
|
<MediaProcessingError className="mx_MAudioBody">
|
||||||
<img src={require("../../../../res/img/warning.svg").default} width="16" height="16" />
|
|
||||||
{ _t("Error processing audio message") }
|
{ _t("Error processing audio message") }
|
||||||
</span>
|
</MediaProcessingError>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContex
|
||||||
import { blobIsAnimated, mayBeAnimated } from '../../../utils/Image';
|
import { blobIsAnimated, mayBeAnimated } from '../../../utils/Image';
|
||||||
import { presentableTextForFile } from "../../../utils/FileUtils";
|
import { presentableTextForFile } from "../../../utils/FileUtils";
|
||||||
import { createReconnectedListener } from '../../../utils/connection';
|
import { createReconnectedListener } from '../../../utils/connection';
|
||||||
|
import MediaProcessingError from './shared/MediaProcessingError';
|
||||||
|
|
||||||
enum Placeholder {
|
enum Placeholder {
|
||||||
NoImage,
|
NoImage,
|
||||||
|
@ -552,10 +553,9 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
|
||||||
|
|
||||||
if (this.state.error) {
|
if (this.state.error) {
|
||||||
return (
|
return (
|
||||||
<div className="mx_MImageBody">
|
<MediaProcessingError className="mx_MImageBody">
|
||||||
<img src={require("../../../../res/img/warning.svg").default} width="16" height="16" />
|
|
||||||
{ _t("Error decrypting image") }
|
{ _t("Error decrypting image") }
|
||||||
</div>
|
</MediaProcessingError>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import { IBodyProps } from "./IBodyProps";
|
||||||
import MFileBody from "./MFileBody";
|
import MFileBody from "./MFileBody";
|
||||||
import { ImageSize, suggestedSize as suggestedVideoSize } from "../../../settings/enums/ImageSize";
|
import { ImageSize, suggestedSize as suggestedVideoSize } from "../../../settings/enums/ImageSize";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
||||||
|
import MediaProcessingError from './shared/MediaProcessingError';
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
decryptedUrl?: string;
|
decryptedUrl?: string;
|
||||||
|
@ -244,10 +245,9 @@ export default class MVideoBody extends React.PureComponent<IBodyProps, IState>
|
||||||
|
|
||||||
if (this.state.error !== null) {
|
if (this.state.error !== null) {
|
||||||
return (
|
return (
|
||||||
<span className="mx_MVideoBody">
|
<MediaProcessingError className="mx_MVideoBody">
|
||||||
<img src={require("../../../../res/img/warning.svg").default} width="16" height="16" />
|
|
||||||
{ _t("Error decrypting video") }
|
{ _t("Error decrypting video") }
|
||||||
</span>
|
</MediaProcessingError>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,16 +21,16 @@ import { _t } from "../../../languageHandler";
|
||||||
import RecordingPlayback from "../audio_messages/RecordingPlayback";
|
import RecordingPlayback from "../audio_messages/RecordingPlayback";
|
||||||
import MAudioBody from "./MAudioBody";
|
import MAudioBody from "./MAudioBody";
|
||||||
import MFileBody from "./MFileBody";
|
import MFileBody from "./MFileBody";
|
||||||
|
import MediaProcessingError from "./shared/MediaProcessingError";
|
||||||
|
|
||||||
export default class MVoiceMessageBody extends MAudioBody {
|
export default class MVoiceMessageBody extends MAudioBody {
|
||||||
// A voice message is an audio file but rendered in a special way.
|
// A voice message is an audio file but rendered in a special way.
|
||||||
public render() {
|
public render() {
|
||||||
if (this.state.error) {
|
if (this.state.error) {
|
||||||
return (
|
return (
|
||||||
<span className="mx_MVoiceMessageBody">
|
<MediaProcessingError className="mx_MVoiceMessageBody">
|
||||||
<img src={require("../../../../res/img/warning.svg").default} width="16" height="16" />
|
|
||||||
{ _t("Error processing voice message") }
|
{ _t("Error processing voice message") }
|
||||||
</span>
|
</MediaProcessingError>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { Icon as WarningIcon } from '../../../../../res/img/warning.svg';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
className?: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MediaProcessingError: React.FC<Props> = ({ className, children }) => (
|
||||||
|
<span className={className}>
|
||||||
|
<WarningIcon className='mx_MediaProcessingError_Icon' width="16" height="16" />
|
||||||
|
{ children }
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default MediaProcessingError;
|
|
@ -21,6 +21,7 @@ import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
||||||
import { EventType } from 'matrix-js-sdk/src/@types/event';
|
import { EventType } from 'matrix-js-sdk/src/@types/event';
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
import { Icon as WarningIcon } from "../../../../../../res/img/warning.svg";
|
||||||
import { _t } from "../../../../../languageHandler";
|
import { _t } from "../../../../../languageHandler";
|
||||||
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
|
||||||
import Modal from "../../../../../Modal";
|
import Modal from "../../../../../Modal";
|
||||||
|
@ -231,7 +232,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
||||||
if (room.getJoinRule() === JoinRule.Public && !this.state.hasAliases) {
|
if (room.getJoinRule() === JoinRule.Public && !this.state.hasAliases) {
|
||||||
aliasWarning = (
|
aliasWarning = (
|
||||||
<div className='mx_SecurityRoomSettingsTab_warning'>
|
<div className='mx_SecurityRoomSettingsTab_warning'>
|
||||||
<img src={require("../../../../../../res/img/warning.svg").default} width={15} height={15} />
|
<WarningIcon width={15} height={15} />
|
||||||
<span>
|
<span>
|
||||||
{ _t("To link to this room, please add an address.") }
|
{ _t("To link to this room, please add an address.") }
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import MediaProcessingError from '../../../../../src/components/views/messages/shared/MediaProcessingError';
|
||||||
|
|
||||||
|
describe('<MediaProcessingError />', () => {
|
||||||
|
const defaultProps = {
|
||||||
|
className: 'test-classname',
|
||||||
|
children: 'Something went wrong',
|
||||||
|
};
|
||||||
|
const getComponent = (props = {}) =>
|
||||||
|
render(<MediaProcessingError {...defaultProps} {...props} />);
|
||||||
|
|
||||||
|
it('renders', () => {
|
||||||
|
const { container } = getComponent();
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`<MediaProcessingError /> renders 1`] = `
|
||||||
|
<div>
|
||||||
|
<span
|
||||||
|
class="test-classname"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_MediaProcessingError_Icon"
|
||||||
|
height="16"
|
||||||
|
width="16"
|
||||||
|
/>
|
||||||
|
Something went wrong
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
`;
|
Loading…
Add table
Add a link
Reference in a new issue