Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit f51a6b6

Browse files
turt2livet3chguy
andauthored
Show file name and size on images on hover (#6511)
* Show simple file name and size on images/videos Fixes element-hq/element-web#18197 * i18n * Fix bad merge * Add hover state tracking * Only show on timeline-like objects * Match new design requirements * Remove video support (deemed not needed) * Colouring and sizing from design * Include file name in lightbox * Revert changes to videos since we don't need them * i18n * Iterate PR Co-authored-by: Michael Telatynski <[email protected]>
1 parent f54d54b commit f51a6b6

File tree

7 files changed

+52
-4
lines changed

7 files changed

+52
-4
lines changed

res/css/views/elements/_ImageView.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ $button-gap: 24px;
7979
font-weight: bold;
8080
}
8181

82+
.mx_ImageView_title {
83+
color: $lightbox-fg-color;
84+
font-size: $font-12px;
85+
}
86+
8287
.mx_ImageView_toolbar {
8388
padding-right: 16px;
8489
pointer-events: initial;

res/css/views/messages/_MImageBody.scss

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,28 @@ limitations under the License.
1717

1818
$timeline-image-border-radius: 8px;
1919

20+
.mx_MImageBody_banner {
21+
position: absolute;
22+
bottom: 4px;
23+
left: 4px;
24+
padding: 4px;
25+
border-radius: $timeline-image-border-radius;
26+
font-size: $font-15px;
27+
28+
pointer-events: none; // let the cursor go through to the media underneath
29+
30+
// Trying to match the width of the image is surprisingly difficult, so arbitrarily break it off early.
31+
max-width: min(100%, 350px);
32+
33+
text-overflow: ellipsis;
34+
white-space: nowrap;
35+
overflow: hidden;
36+
37+
// Hardcoded colours because it's the same on all themes
38+
background-color: rgba(0, 0, 0, 0.6);
39+
color: #ffffff;
40+
}
41+
2042
.mx_MImageBody_placeholder {
2143
// Position the placeholder on top of the thumbnail, so that the reveal animation can work
2244
position: absolute;

src/components/views/elements/ImageView.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import UIStore from '../../../stores/UIStore';
3838
import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload";
3939
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
4040
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
41+
import { presentableTextForFile } from "../../../utils/FileUtils";
4142

4243
// Max scale to keep gaps around the image
4344
const MAX_SCALE = 0.95;
@@ -546,6 +547,9 @@ export default class ImageView extends React.Component<IProps, IState> {
546547
>
547548
<div className="mx_ImageView_panel">
548549
{ info }
550+
<div className="mx_ImageView_title">
551+
{ presentableTextForFile(this.props.mxEvent.getContent(), _t("Image"), true) }
552+
</div>
549553
<div className="mx_ImageView_toolbar">
550554
{ zoomOutButton }
551555
{ zoomInButton }

src/components/views/messages/MFileBody.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ export default class MFileBody extends React.Component<IProps, IState> {
344344
</a>
345345
{ this.context.timelineRenderingType === TimelineRenderingType.File && (
346346
<div className="mx_MImageBody_size">
347-
{ this.content.info && this.content.info.size ? filesize(this.content.info.size) : "" }
347+
{ this.content.info?.size ? filesize(this.content.info.size) : "" }
348348
</div>
349349
) }
350350
</div> }

src/components/views/messages/MImageBody.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import { ImageSize, suggestedSize as suggestedImageSize } from "../../../setting
3737
import { MatrixClientPeg } from '../../../MatrixClientPeg';
3838
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
3939
import { blobIsAnimated, mayBeAnimated } from '../../../utils/Image';
40+
import { presentableTextForFile } from "../../../utils/FileUtils";
4041

4142
enum Placeholder {
4243
NoImage,
@@ -446,6 +447,21 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
446447
gifLabel = <p className="mx_MImageBody_gifLabel">GIF</p>;
447448
}
448449

450+
let banner: JSX.Element;
451+
const isTimeline = [
452+
TimelineRenderingType.Room,
453+
TimelineRenderingType.Search,
454+
TimelineRenderingType.Thread,
455+
TimelineRenderingType.Notification,
456+
].includes(this.context.timelineRenderingType);
457+
if (this.state.showImage && this.state.hover && isTimeline) {
458+
banner = (
459+
<span className="mx_MImageBody_banner">
460+
{ presentableTextForFile(content, _t("Image"), true, true) }
461+
</span>
462+
);
463+
}
464+
449465
const classes = classNames({
450466
'mx_MImageBody_placeholder': true,
451467
'mx_MImageBody_placeholder--blurhash': this.props.mxEvent.getContent().info?.[BLURHASH_FIELD],
@@ -473,6 +489,7 @@ export default class MImageBody extends React.Component<IBodyProps, IState> {
473489
<div style={sizing}>
474490
{ img }
475491
{ gifLabel }
492+
{ banner }
476493
</div>
477494

478495
{ /* HACK: This div fills out space while the image loads, to prevent scroll jumps */ }

src/i18n/strings/en_EN.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2134,9 +2134,9 @@
21342134
"Error decrypting attachment": "Error decrypting attachment",
21352135
"Decrypt %(text)s": "Decrypt %(text)s",
21362136
"Invalid file%(extra)s": "Invalid file%(extra)s",
2137+
"Image": "Image",
21372138
"Error decrypting image": "Error decrypting image",
21382139
"Show image": "Show image",
2139-
"Image": "Image",
21402140
"Join the conference at the top of this room": "Join the conference at the top of this room",
21412141
"Join the conference from the room information card on the right": "Join the conference from the room information card on the right",
21422142
"Video conference ended by %(senderName)s": "Video conference ended by %(senderName)s",

src/utils/FileUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function presentableTextForFile(
3737
shortened = false,
3838
): string {
3939
let text = fallbackText;
40-
if (content.body && content.body.length > 0) {
40+
if (content.body?.length > 0) {
4141
// The content body should be the name of the file including a
4242
// file extension.
4343
text = content.body;
@@ -58,7 +58,7 @@ export function presentableTextForFile(
5858
text = `${fileName}...${extension}`;
5959
}
6060

61-
if (content.info && content.info.size && withSize) {
61+
if (content.info?.size && withSize) {
6262
// If we know the size of the file then add it as human readable
6363
// string to the end of the link text so that the user knows how
6464
// big a file they are downloading.

0 commit comments

Comments
 (0)