Show generic attachment for non-loading/too-large images/videos
This commit is contained in:
parent
d0c4152d99
commit
8290146721
9 changed files with 507 additions and 144 deletions
|
@ -880,15 +880,6 @@
|
|||
"description":
|
||||
"Used in alt tag of thumbnail images inside of an embedded message quote"
|
||||
},
|
||||
"imageFailedToLoad": {
|
||||
"message": "Image failed to load",
|
||||
"description": "When an image attachment is missing, this message is shown"
|
||||
},
|
||||
"videoScreenshotFailedToLoad": {
|
||||
"message": "Video screenshot failed to load",
|
||||
"description":
|
||||
"When a attachment video screenshot is missing, this message is shown"
|
||||
},
|
||||
"imageAttachmentAlt": {
|
||||
"message": "Image attached to message",
|
||||
"description": "Used in alt tag of image attachment"
|
||||
|
|
|
@ -293,21 +293,6 @@
|
|||
border-bottom-right-radius: 16px;
|
||||
}
|
||||
|
||||
.module-message__broken-image {
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.3px;
|
||||
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
color: $color-light-90;
|
||||
}
|
||||
|
||||
.module-message__broken-image--incoming {
|
||||
color: $color-white;
|
||||
}
|
||||
|
||||
.module-message__video-overlay__circle {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
|
@ -331,23 +316,6 @@
|
|||
@include color-svg('../images/play.svg', $color-signal-blue);
|
||||
}
|
||||
|
||||
.module-message__broken-video-screenshot {
|
||||
font-size: 11px;
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.3px;
|
||||
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
color: $color-light-90;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.module-message__broken-video-screenshot--incoming {
|
||||
color: $color-white;
|
||||
}
|
||||
|
||||
.module-message__audio-attachment {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ const contact = {
|
|||
authorColor="green"
|
||||
direction="incoming"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -36,6 +37,7 @@ const contact = {
|
|||
direction="outgoing"
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -45,6 +47,7 @@ const contact = {
|
|||
direction="incoming"
|
||||
collapseMetadata
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -54,6 +57,7 @@ const contact = {
|
|||
collapseMetadata
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -85,11 +89,13 @@ const contact = {
|
|||
authorColor="green"
|
||||
direction="incoming"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}/></li>
|
||||
<li><Message
|
||||
direction="outgoing"
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}/></li>
|
||||
</util.ConversationContext>;
|
||||
```
|
||||
|
@ -123,6 +129,7 @@ const contact = {
|
|||
authorAvatarPath={util.gifObjectUrl}
|
||||
direction="incoming"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -134,6 +141,7 @@ const contact = {
|
|||
conversationType="group"
|
||||
collapseMetadata
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -144,6 +152,7 @@ const contact = {
|
|||
authorName="Mr. Fire"
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -176,6 +185,7 @@ const contact = {
|
|||
authorColor="green"
|
||||
direction="incoming"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -184,6 +194,7 @@ const contact = {
|
|||
direction="outgoing"
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -193,6 +204,7 @@ const contact = {
|
|||
direction="incoming"
|
||||
collapseMetadata
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -202,6 +214,7 @@ const contact = {
|
|||
collapseMetadata
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -232,6 +245,7 @@ const contact = {
|
|||
authorColor="green"
|
||||
direction="incoming"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -240,6 +254,7 @@ const contact = {
|
|||
direction="outgoing"
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -249,6 +264,7 @@ const contact = {
|
|||
direction="incoming"
|
||||
collapseMetadata
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -258,6 +274,7 @@ const contact = {
|
|||
collapseMetadata
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -290,6 +307,7 @@ const contact = {
|
|||
authorColor="green"
|
||||
direction="incoming"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -298,6 +316,7 @@ const contact = {
|
|||
direction="outgoing"
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -307,6 +326,7 @@ const contact = {
|
|||
direction="incoming"
|
||||
collapseMetadata
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -316,6 +336,7 @@ const contact = {
|
|||
collapseMetadata
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -343,6 +364,7 @@ const contact = {
|
|||
authorColor="green"
|
||||
direction="incoming"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -351,6 +373,7 @@ const contact = {
|
|||
direction="outgoing"
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -360,6 +383,7 @@ const contact = {
|
|||
direction="incoming"
|
||||
collapseMetadata
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -369,6 +393,7 @@ const contact = {
|
|||
collapseMetadata
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -385,6 +410,7 @@ const contact = {};
|
|||
authorColor="green"
|
||||
direction="incoming"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -393,6 +419,7 @@ const contact = {};
|
|||
direction="outgoing"
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -402,6 +429,7 @@ const contact = {};
|
|||
direction="incoming"
|
||||
collapseMetadata
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -411,6 +439,7 @@ const contact = {};
|
|||
collapseMetadata
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contact}
|
||||
/>
|
||||
</li>
|
||||
|
@ -461,6 +490,7 @@ const contactWithoutAccount = {
|
|||
authorColor="green"
|
||||
direction="incoming"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contactWithAccount}
|
||||
/>
|
||||
</li>
|
||||
|
@ -470,6 +500,7 @@ const contactWithoutAccount = {
|
|||
direction="outgoing"
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contactWithAccount}
|
||||
/>
|
||||
</li>
|
||||
|
@ -479,6 +510,7 @@ const contactWithoutAccount = {
|
|||
authorColor="green"
|
||||
direction="incoming"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contactWithAccount}
|
||||
/>
|
||||
</li>
|
||||
|
@ -488,6 +520,7 @@ const contactWithoutAccount = {
|
|||
direction="outgoing"
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contactWithAccount}
|
||||
/>
|
||||
</li>
|
||||
|
@ -498,6 +531,7 @@ const contactWithoutAccount = {
|
|||
direction="incoming"
|
||||
collapseMetadata
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contactWithoutAccount}
|
||||
/>
|
||||
</li>
|
||||
|
@ -508,6 +542,7 @@ const contactWithoutAccount = {
|
|||
collapseMetadata
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contactWithoutAccount}
|
||||
/>
|
||||
</li>
|
||||
|
@ -518,6 +553,7 @@ const contactWithoutAccount = {
|
|||
direction="incoming"
|
||||
collapseMetadata
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contactWithoutAccount}
|
||||
/>
|
||||
</li>
|
||||
|
@ -528,6 +564,7 @@ const contactWithoutAccount = {
|
|||
collapseMetadata
|
||||
status="delivered"
|
||||
i18n={util.i18n}
|
||||
timestamp={Date.now()}
|
||||
contact={contactWithoutAccount}
|
||||
/>
|
||||
</li>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -128,6 +128,12 @@ function isAudio(attachment?: Attachment) {
|
|||
);
|
||||
}
|
||||
|
||||
function canDisplayImage(attachment?: Attachment) {
|
||||
const { height, width } = attachment || { height: 0, width: 0 };
|
||||
|
||||
return height > 0 && height <= 4096 && width > 0 && width <= 4096;
|
||||
}
|
||||
|
||||
function getInitial(name: string): string {
|
||||
return name.trim()[0] || '#';
|
||||
}
|
||||
|
@ -267,8 +273,10 @@ export class Message extends React.Component<Props, State> {
|
|||
return null;
|
||||
}
|
||||
|
||||
const canDisplayAttachment = canDisplayImage(attachment);
|
||||
const withImageNoCaption = Boolean(
|
||||
!text &&
|
||||
canDisplayAttachment &&
|
||||
!imageBroken &&
|
||||
((isImage(attachment) && hasImage(attachment)) ||
|
||||
(isVideo(attachment) && hasVideoScreenshot(attachment)))
|
||||
|
@ -382,23 +390,11 @@ export class Message extends React.Component<Props, State> {
|
|||
const withContentBelow = withCaption || !collapseMetadata;
|
||||
const withContentAbove =
|
||||
quote || (conversationType === 'group' && direction === 'incoming');
|
||||
const displayImage = canDisplayImage(attachment);
|
||||
|
||||
if (isImage(attachment)) {
|
||||
if (imageBroken || !attachment.url) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'module-message__broken-image',
|
||||
`module-message__broken-image--${direction}`
|
||||
)}
|
||||
>
|
||||
{i18n('imageFailedToLoad')}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isImage(attachment) && displayImage && !imageBroken && attachment.url) {
|
||||
// Calculating height to prevent reflow when image loads
|
||||
const height = Math.max(MINIMUM_IMG_HEIGHT, attachment.height || 0);
|
||||
const imageHeight = Math.max(MINIMUM_IMG_HEIGHT, attachment.height || 0);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -417,7 +413,7 @@ export class Message extends React.Component<Props, State> {
|
|||
<img
|
||||
onError={this.handleImageErrorBound}
|
||||
className="module-message__img-attachment"
|
||||
height={Math.min(MAXIMUM_IMG_HEIGHT, height)}
|
||||
height={Math.min(MAXIMUM_IMG_HEIGHT, imageHeight)}
|
||||
src={attachment.url}
|
||||
alt={i18n('imageAttachmentAlt')}
|
||||
/>
|
||||
|
@ -437,25 +433,19 @@ export class Message extends React.Component<Props, State> {
|
|||
) : null}
|
||||
</div>
|
||||
);
|
||||
} else if (isVideo(attachment)) {
|
||||
} else if (
|
||||
isVideo(attachment) &&
|
||||
displayImage &&
|
||||
!imageBroken &&
|
||||
attachment.screenshot &&
|
||||
attachment.screenshot.url
|
||||
) {
|
||||
const { screenshot } = attachment;
|
||||
if (imageBroken || !screenshot || !screenshot.url) {
|
||||
return (
|
||||
<div
|
||||
role="button"
|
||||
onClick={onClickAttachment}
|
||||
className={classNames(
|
||||
'module-message__broken-video-screenshot',
|
||||
`module-message__broken-video-screenshot--${direction}`
|
||||
)}
|
||||
>
|
||||
{i18n('videoScreenshotFailedToLoad')}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Calculating height to prevent reflow when image loads
|
||||
const height = Math.max(MINIMUM_IMG_HEIGHT, screenshot.height || 0);
|
||||
const imageHeight = Math.max(
|
||||
MINIMUM_IMG_HEIGHT,
|
||||
attachment.screenshot.height || 0
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -475,7 +465,7 @@ export class Message extends React.Component<Props, State> {
|
|||
onError={this.handleImageErrorBound}
|
||||
className="module-message__img-attachment"
|
||||
alt={i18n('videoAttachmentAlt')}
|
||||
height={Math.min(MAXIMUM_IMG_HEIGHT, height)}
|
||||
height={Math.min(MAXIMUM_IMG_HEIGHT, imageHeight)}
|
||||
src={screenshot.url}
|
||||
/>
|
||||
<div
|
||||
|
|
|
@ -1066,6 +1066,8 @@
|
|||
url: util.gifObjectUrl,
|
||||
fileName: 'pi.gif',
|
||||
contentType: 'image/gif',
|
||||
width: 320,
|
||||
height: 240,
|
||||
}}
|
||||
text="About six"
|
||||
i18n={util.i18n}
|
||||
|
@ -1085,6 +1087,8 @@
|
|||
url: util.gifObjectUrl,
|
||||
fileName: 'pi.gif',
|
||||
contentType: 'image/gif',
|
||||
width: 320,
|
||||
height: 240,
|
||||
}}
|
||||
authorColor="green"
|
||||
text="About six"
|
||||
|
@ -1112,6 +1116,8 @@
|
|||
url: util.gifObjectUrl,
|
||||
fileName: 'pi.gif',
|
||||
contentType: 'image/gif',
|
||||
width: 320,
|
||||
height: 240,
|
||||
}}
|
||||
i18n={util.i18n}
|
||||
quote={{
|
||||
|
@ -1130,6 +1136,8 @@
|
|||
url: util.gifObjectUrl,
|
||||
fileName: 'pi.gif',
|
||||
contentType: 'image/gif',
|
||||
width: 320,
|
||||
height: 240,
|
||||
}}
|
||||
authorColor="green"
|
||||
i18n={util.i18n}
|
||||
|
@ -1156,6 +1164,8 @@
|
|||
url: util.portraitYellowObjectUrl,
|
||||
fileName: 'pi.gif',
|
||||
contentType: 'image/gif',
|
||||
width: 20,
|
||||
height: 200,
|
||||
}}
|
||||
i18n={util.i18n}
|
||||
quote={{
|
||||
|
@ -1174,6 +1184,8 @@
|
|||
url: util.portraitYellowObjectUrl,
|
||||
fileName: 'pi.gif',
|
||||
contentType: 'image/gif',
|
||||
width: 20,
|
||||
height: 200,
|
||||
}}
|
||||
authorColor="green"
|
||||
i18n={util.i18n}
|
||||
|
@ -1200,9 +1212,13 @@
|
|||
screenshot: {
|
||||
url: util.pngObjectUrl,
|
||||
contentType: 'image/png',
|
||||
width: 800,
|
||||
height: 1200,
|
||||
},
|
||||
fileName: 'freezing_bubble.mp4',
|
||||
contentType: 'video/mp4',
|
||||
width: 800,
|
||||
height: 1200,
|
||||
}}
|
||||
i18n={util.i18n}
|
||||
quote={{
|
||||
|
@ -1221,9 +1237,13 @@
|
|||
screenshot: {
|
||||
url: util.pngObjectUrl,
|
||||
contentType: 'image/png',
|
||||
width: 800,
|
||||
height: 1200,
|
||||
},
|
||||
fileName: 'freezing_bubble.mp4',
|
||||
contentType: 'video/mp4',
|
||||
width: 800,
|
||||
height: 1200,
|
||||
}}
|
||||
authorColor="green"
|
||||
i18n={util.i18n}
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
/**
|
||||
* @prettier
|
||||
*/
|
||||
export type AttachmentType = 'media' | 'documents';
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
/**
|
||||
* @prettier
|
||||
*/
|
||||
import { AttachmentType } from './AttachmentType';
|
||||
import { Message } from './Message';
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue