diff --git a/src/components/views/messages/MFileBody.tsx b/src/components/views/messages/MFileBody.tsx index b1e42976db..772b8c8f70 100644 --- a/src/components/views/messages/MFileBody.tsx +++ b/src/components/views/messages/MFileBody.tsx @@ -23,7 +23,7 @@ import { replaceableComponent } from "../../../utils/replaceableComponent"; import { mediaFromContent } from "../../../customisations/Media"; import ErrorDialog from "../dialogs/ErrorDialog"; import { TileShape } from "../rooms/EventTile"; -import { IContent } from "matrix-js-sdk/src"; +import { presentableTextForFile } from "../../../utils/FileUtils"; import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; import { IBodyProps } from "./IBodyProps"; @@ -93,35 +93,6 @@ export function computedStyle(element: HTMLElement) { return cssText; } -/** - * Extracts a human readable label for the file attachment to use as - * link text. - * - * @param {Object} content The "content" key of the matrix event. - * @param {boolean} withSize Whether to include size information. Default true. - * @return {string} the human readable link text for the attachment. - */ -export function presentableTextForFile(content: IContent, withSize = true): string { - let linkText = _t("Attachment"); - if (content.body && content.body.length > 0) { - // The content body should be the name of the file including a - // file extension. - linkText = content.body; - } - - if (content.info && content.info.size && withSize) { - // If we know the size of the file then add it as human readable - // string to the end of the link text so that the user knows how - // big a file they are downloading. - // The content.info also contains a MIME-type but we don't display - // it since it is "ugly", users generally aren't aware what it - // means and the type of the attachment can usually be inferrered - // from the file extension. - linkText += ' (' + filesize(content.info.size) + ')'; - } - return linkText; -} - interface IProps extends IBodyProps { /* whether or not to show the default placeholder for the file. Defaults to true. */ showGenericPlaceholder: boolean; @@ -173,7 +144,7 @@ export default class MFileBody extends React.Component {
- { presentableTextForFile(content, false) } + { presentableTextForFile(content, _t("Attachment"), false) }
); diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index e641582962..44c15d50e7 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -404,7 +404,7 @@ export default class MImageBody extends React.Component { } // Overidden by MStickerBody - protected getFileBody(): JSX.Element { + protected getFileBody(): string | JSX.Element { // We only ever need the download bar if we're appearing outside of the timeline if (this.props.tileShape) { return ; diff --git a/src/components/views/messages/MImageReplyBody.tsx b/src/components/views/messages/MImageReplyBody.tsx index 5f7f0da3ca..8d92920226 100644 --- a/src/components/views/messages/MImageReplyBody.tsx +++ b/src/components/views/messages/MImageReplyBody.tsx @@ -16,9 +16,11 @@ limitations under the License. import React from "react"; import MImageBody from "./MImageBody"; -import { presentableTextForFile } from "./MFileBody"; +import { presentableTextForFile } from "../../../utils/FileUtils"; import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; import SenderProfile from "./SenderProfile"; +import { EventType } from "matrix-js-sdk/src/@types/event"; +import { _t } from "../../../languageHandler"; const FORCED_IMAGE_HEIGHT = 44; @@ -32,8 +34,9 @@ export default class MImageReplyBody extends MImageBody { } // Don't show "Download this_file.png ..." - public getFileBody(): JSX.Element { - return <>{ presentableTextForFile(this.props.mxEvent.getContent()) }; + public getFileBody(): string { + const sticker = this.props.mxEvent.getType() === EventType.Sticker; + return presentableTextForFile(this.props.mxEvent.getContent(), sticker ? _t("Sticker") : _t("Image"), !sticker); } render() { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index f081ec823b..e1f3dcc828 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -657,6 +657,7 @@ "This homeserver has exceeded one of its resource limits.": "This homeserver has exceeded one of its resource limits.", "Please contact your service administrator to continue using the service.": "Please contact your service administrator to continue using the service.", "Unable to connect to Homeserver. Retrying...": "Unable to connect to Homeserver. Retrying...", + "Attachment": "Attachment", "%(items)s and %(count)s others|other": "%(items)s and %(count)s others", "%(items)s and %(count)s others|one": "%(items)s and one other", "%(items)s and %(lastItem)s": "%(items)s and %(lastItem)s", @@ -1878,13 +1879,14 @@ "Retry": "Retry", "Reply": "Reply", "Message Actions": "Message Actions", - "Attachment": "Attachment", "Error decrypting attachment": "Error decrypting attachment", "Decrypt %(text)s": "Decrypt %(text)s", "Download %(text)s": "Download %(text)s", "Invalid file%(extra)s": "Invalid file%(extra)s", "Error decrypting image": "Error decrypting image", "Show image": "Show image", + "Sticker": "Sticker", + "Image": "Image", "Join the conference at the top of this room": "Join the conference at the top of this room", "Join the conference from the room information card on the right": "Join the conference from the room information card on the right", "Video conference ended by %(senderName)s": "Video conference ended by %(senderName)s", diff --git a/src/utils/FileUtils.ts b/src/utils/FileUtils.ts new file mode 100644 index 0000000000..355fa2135c --- /dev/null +++ b/src/utils/FileUtils.ts @@ -0,0 +1,54 @@ +/* +Copyright 2015 - 2021 The Matrix.org Foundation C.I.C. +Copyright 2021 Šimon Brandner + +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 filesize from 'filesize'; +import { IMediaEventContent } from '../customisations/models/IMediaEventContent'; +import { _t } from '../languageHandler'; + +/** + * Extracts a human readable label for the file attachment to use as + * link text. + * + * @param {IMediaEventContent} content The "content" key of the matrix event. + * @param {string} fallbackText The fallback text + * @param {boolean} withSize Whether to include size information. Default true. + * @return {string} the human readable link text for the attachment. + */ +export function presentableTextForFile( + content: IMediaEventContent, + fallbackText = _t("Attachment"), + withSize = true, +): string { + let text = fallbackText; + if (content.body && content.body.length > 0) { + // The content body should be the name of the file including a + // file extension. + text = content.body; + } + + if (content.info && content.info.size && withSize) { + // If we know the size of the file then add it as human readable + // string to the end of the link text so that the user knows how + // big a file they are downloading. + // The content.info also contains a MIME-type but we don't display + // it since it is "ugly", users generally aren't aware what it + // means and the type of the attachment can usually be inferrered + // from the file extension. + text += ' (' + filesize(content.info.size) + ')'; + } + return text; +}