Skip to content

Commit

Permalink
Merge pull request #3170 from yougotwill/fix/ses-2546/attachment_prev…
Browse files Browse the repository at this point in the history
…iew_loading

Fix attachment previews
  • Loading branch information
Bilb authored Aug 21, 2024
2 parents f7d87e0 + 3fd37bb commit fa72be5
Show file tree
Hide file tree
Showing 12 changed files with 291 additions and 213 deletions.
1 change: 1 addition & 0 deletions stylesheets/_modules.scss
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
line-height: 16px;
letter-spacing: 0.3px;
margin-top: 3px;
text-align: start;
white-space: nowrap;
}

Expand Down
92 changes: 71 additions & 21 deletions ts/components/conversation/Image.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
import classNames from 'classnames';
import { useCallback } from 'react';
import { useCallback, useEffect, useState } from 'react';
import styled from 'styled-components';

import { isNumber } from 'lodash';
import { useDisableDrag } from '../../hooks/useDisableDrag';
import { useEncryptedFileFetch } from '../../hooks/useEncryptedFileFetch';
import { AttachmentType, AttachmentTypeWithPath } from '../../types/Attachment';
import { Spinner } from '../loading';
import { MessageGenericAttachment } from './message/message-content/MessageGenericAttachment';
import { useEncryptedFileFetch } from '../../hooks/useEncryptedFileFetch';
import { useMessageIdFromContext } from '../../contexts/MessageIdContext';
import {
useMessageDirection,
useMessageSelected,
useMessageTimestamp,
} from '../../state/selectors';

type Props = {
alt: string;
attachment: AttachmentTypeWithPath | AttachmentType;
url: string | undefined; // url is undefined if the message is not visible yet
/** undefined if the message is not visible yet, '' if the attachment is broken */
url: string | undefined;
imageBroken?: boolean;

height?: number | string;
width?: number | string;
Expand All @@ -24,8 +33,8 @@ type Props = {
playIconOverlay?: boolean;
softCorners: boolean;
forceSquare?: boolean;
dropShadow?: boolean;
attachmentIndex?: number;
highlight?: boolean;

onClick?: (attachment: AttachmentTypeWithPath | AttachmentType) => void;
onClickClose?: (attachment: AttachmentTypeWithPath | AttachmentType) => void;
Expand All @@ -46,6 +55,7 @@ export const Image = (props: Props) => {
const {
alt,
attachment,
imageBroken,
closeButton,
darkOverlay,
height: _height,
Expand All @@ -56,34 +66,74 @@ export const Image = (props: Props) => {
playIconOverlay,
softCorners,
forceSquare,
dropShadow,
attachmentIndex,
highlight,
url,
width: _width,
} = props;

const onErrorUrlFilterering = useCallback(() => {
if (url && onError) {
onError();
}
}, [url, onError]);
const messageId = useMessageIdFromContext();
const dropShadow = useMessageSelected(messageId);
const direction = useMessageDirection(messageId);
/** used for debugging */
const timestamp = useMessageTimestamp(messageId);

const disableDrag = useDisableDrag();
const { loading, urlToLoad } = useEncryptedFileFetch(
url,
attachment.contentType,
false,
timestamp
);

const { caption } = attachment || { caption: null };
let { pending } = attachment || { pending: true };
if (!url) {
// force pending to true if the url is undefined, so we show a loader while decrypting the attachemtn
pending = true;
}
const [pending, setPending] = useState<boolean>(attachment.pending || true);
const [mounted, setMounted] = useState<boolean>(
(!loading || !pending) && urlToLoad === undefined
);

const canClick = onClick && !pending;
const role = canClick ? 'button' : undefined;
const { loading, urlToLoad } = useEncryptedFileFetch(url || '', attachment.contentType, false);
// data will be url if loading is finished and '' if not
const srcData = !loading ? urlToLoad : '';

const onErrorUrlFilterering = useCallback(() => {
if (mounted && url && urlToLoad === '' && onError) {
onError();
setPending(false);
}
}, [mounted, onError, url, urlToLoad]);

const width = isNumber(_width) ? `${_width}px` : _width;
const height = isNumber(_height) ? `${_height}px` : _height;

useEffect(() => {
if (mounted && url === '') {
setPending(false);
onErrorUrlFilterering();
}

if (mounted && imageBroken && urlToLoad === '') {
setPending(false);
onErrorUrlFilterering();
}

if (url) {
setPending(false);
setMounted(!loading && !pending);
}
}, [imageBroken, loading, mounted, onErrorUrlFilterering, pending, url, urlToLoad]);

if (mounted && imageBroken) {
return (
<MessageGenericAttachment
attachment={attachment as AttachmentTypeWithPath}
pending={false}
highlight={!!highlight}
selected={!!dropShadow} // dropshadow is selected
direction={direction}
/>
);
}

return (
<div
role={role}
Expand All @@ -107,7 +157,7 @@ export const Image = (props: Props) => {
}}
data-attachmentindex={attachmentIndex}
>
{pending || loading ? (
{!mounted ? (
<div
className="module-image__loading-placeholder"
style={{
Expand Down Expand Up @@ -137,7 +187,7 @@ export const Image = (props: Props) => {
width: forceSquare ? width : '',
height: forceSquare ? height : '',
}}
src={srcData}
src={urlToLoad}
onDragStart={disableDrag}
/>
)}
Expand Down Expand Up @@ -166,7 +216,7 @@ export const Image = (props: Props) => {
className="module-image__close-button"
/>
) : null}
{!(pending || loading) && playIconOverlay ? (
{mounted && playIconOverlay ? (
<div className="module-image__play-overlay__circle">
<div className="module-image__play-overlay__icon" />
</div>
Expand Down
27 changes: 15 additions & 12 deletions ts/components/conversation/ImageGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import {
} from '../../types/Attachment';

import { useIsMessageVisible } from '../../contexts/isMessageVisibleContext';
import { useMessageSelected } from '../../state/selectors';
import { THUMBNAIL_SIDE } from '../../types/attachments/VisualAttachment';
import { Image } from './Image';

type Props = {
attachments: Array<AttachmentTypeWithPath>;
onError: () => void;
imageBroken: boolean;
highlight: boolean;
onClickAttachment?: (attachment: AttachmentTypeWithPath | AttachmentType) => void;
messageId?: string;
};

const StyledImageGrid = styled.div<{ flexDirection: 'row' | 'column' }>`
Expand All @@ -33,17 +33,17 @@ const Row = (
renderedSize: number;
startIndex: number;
totalAttachmentsCount: number;
selected: boolean;
}
) => {
const {
attachments,
imageBroken,
highlight,
onError,
renderedSize,
startIndex,
onClickAttachment,
totalAttachmentsCount,
selected,
} = props;
const isMessageVisible = useIsMessageVisible();
const moreMessagesOverlay = totalAttachmentsCount > 3;
Expand All @@ -64,11 +64,12 @@ const Row = (
url={isMessageVisible ? getThumbnailUrl(attachment) : undefined}
attachmentIndex={startIndex + index}
onClick={onClickAttachment}
imageBroken={imageBroken}
highlight={highlight}
onError={onError}
softCorners={true}
darkOverlay={showOverlay}
overlayText={showOverlay ? moreMessagesOverlayText : undefined}
dropShadow={selected}
/>
);
})}
Expand All @@ -77,9 +78,7 @@ const Row = (
};

export const ImageGrid = (props: Props) => {
const { attachments, onError, onClickAttachment, messageId } = props;

const selected = useMessageSelected(messageId);
const { attachments, imageBroken, highlight, onError, onClickAttachment } = props;

if (!attachments || !attachments.length) {
return null;
Expand All @@ -90,12 +89,13 @@ export const ImageGrid = (props: Props) => {
<StyledImageGrid flexDirection={'row'}>
<Row
attachments={attachments.slice(0, 1)}
imageBroken={imageBroken}
highlight={highlight}
onError={onError}
onClickAttachment={onClickAttachment}
renderedSize={THUMBNAIL_SIDE}
startIndex={0}
totalAttachmentsCount={attachments.length}
selected={selected}
/>
</StyledImageGrid>
);
Expand All @@ -107,12 +107,13 @@ export const ImageGrid = (props: Props) => {
<StyledImageGrid flexDirection={'row'}>
<Row
attachments={attachments.slice(0, 2)}
imageBroken={imageBroken}
highlight={highlight}
onError={onError}
onClickAttachment={onClickAttachment}
renderedSize={THUMBNAIL_SIDE}
startIndex={0}
totalAttachmentsCount={attachments.length}
selected={selected}
/>
</StyledImageGrid>
);
Expand All @@ -125,23 +126,25 @@ export const ImageGrid = (props: Props) => {
<StyledImageGrid flexDirection={'row'}>
<Row
attachments={attachments.slice(0, 1)}
imageBroken={imageBroken}
highlight={highlight}
onError={onError}
onClickAttachment={onClickAttachment}
renderedSize={THUMBNAIL_SIDE}
startIndex={0}
totalAttachmentsCount={attachments.length}
selected={selected}
/>

<StyledImageGrid flexDirection={'column'}>
<Row
attachments={attachments.slice(1, 3)}
imageBroken={imageBroken}
highlight={highlight}
onError={onError}
onClickAttachment={onClickAttachment}
renderedSize={columnImageSide}
startIndex={1}
totalAttachmentsCount={attachments.length}
selected={selected}
/>
</StyledImageGrid>
</StyledImageGrid>
Expand Down
Loading

0 comments on commit fa72be5

Please sign in to comment.