Show attachment download progress, new stop button to cancel
Co-authored-by: Jamie Kyle <jamie@signal.org>
This commit is contained in:
parent
025841e5bb
commit
2741fbb5d2
78 changed files with 2192 additions and 562 deletions
|
@ -20,6 +20,7 @@ import {
|
|||
import { Image, CurveType } from './Image';
|
||||
|
||||
import type { LocalizerType, ThemeType } from '../../types/Util';
|
||||
import { AttachmentDetailPill } from './AttachmentDetailPill';
|
||||
|
||||
export type DirectionType = 'incoming' | 'outgoing';
|
||||
|
||||
|
@ -39,7 +40,9 @@ export type Props = {
|
|||
theme?: ThemeType;
|
||||
|
||||
onError: () => void;
|
||||
onClick?: (attachment: AttachmentType) => void;
|
||||
showVisualAttachment: (attachment: AttachmentType) => void;
|
||||
cancelDownload: () => void;
|
||||
startDownload: () => void;
|
||||
};
|
||||
|
||||
const GAP = 1;
|
||||
|
@ -108,7 +111,9 @@ export function ImageGrid({
|
|||
isSticker,
|
||||
stickerSize,
|
||||
onError,
|
||||
onClick,
|
||||
showVisualAttachment,
|
||||
cancelDownload,
|
||||
startDownload,
|
||||
shouldCollapseAbove,
|
||||
shouldCollapseBelow,
|
||||
tabIndex,
|
||||
|
@ -127,10 +132,46 @@ export function ImageGrid({
|
|||
|
||||
const withBottomOverlay = Boolean(bottomOverlay && !withContentBelow);
|
||||
|
||||
const startDownloadClick = React.useCallback(
|
||||
(event: React.MouseEvent) => {
|
||||
if (startDownload) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
startDownload();
|
||||
}
|
||||
},
|
||||
[startDownload]
|
||||
);
|
||||
const startDownloadKeyDown = React.useCallback(
|
||||
(event: React.KeyboardEvent<HTMLButtonElement>) => {
|
||||
if (startDownload && (event.key === 'Enter' || event.key === 'Space')) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
startDownload();
|
||||
}
|
||||
},
|
||||
[startDownload]
|
||||
);
|
||||
|
||||
if (!attachments || !attachments.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const detailPill = (
|
||||
<AttachmentDetailPill
|
||||
attachments={attachments}
|
||||
i18n={i18n}
|
||||
startDownload={startDownload}
|
||||
cancelDownload={cancelDownload}
|
||||
/>
|
||||
);
|
||||
const downloadPill = renderDownloadPill({
|
||||
attachments,
|
||||
i18n,
|
||||
startDownloadClick,
|
||||
startDownloadKeyDown,
|
||||
});
|
||||
|
||||
if (attachments.length === 1 || !areAllAttachmentsVisual(attachments)) {
|
||||
const { height, width } = getImageDimensions(
|
||||
attachments[0],
|
||||
|
@ -165,9 +206,12 @@ export function ImageGrid({
|
|||
getUrl(attachments[0]) ?? attachments[0].thumbnailFromBackup?.url
|
||||
}
|
||||
tabIndex={tabIndex}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
{detailPill}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -190,7 +234,9 @@ export function ImageGrid({
|
|||
width={150}
|
||||
cropWidth={GAP}
|
||||
url={getThumbnailUrl(attachments[0])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
|
@ -207,9 +253,13 @@ export function ImageGrid({
|
|||
width={150}
|
||||
attachment={attachments[1]}
|
||||
url={getThumbnailUrl(attachments[1])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
{detailPill}
|
||||
{downloadPill}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -232,7 +282,9 @@ export function ImageGrid({
|
|||
width={200}
|
||||
cropWidth={GAP}
|
||||
url={getUrl(attachments[0])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
<div className="module-image-grid__column">
|
||||
|
@ -248,7 +300,9 @@ export function ImageGrid({
|
|||
attachment={attachments[1]}
|
||||
playIconOverlay={isVideoAttachment(attachments[1])}
|
||||
url={getThumbnailUrl(attachments[1])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
|
@ -264,10 +318,14 @@ export function ImageGrid({
|
|||
attachment={attachments[2]}
|
||||
playIconOverlay={isVideoAttachment(attachments[2])}
|
||||
url={getThumbnailUrl(attachments[2])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
</div>
|
||||
{detailPill}
|
||||
{downloadPill}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -291,7 +349,9 @@ export function ImageGrid({
|
|||
cropHeight={GAP}
|
||||
cropWidth={GAP}
|
||||
url={getThumbnailUrl(attachments[0])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
|
@ -307,7 +367,9 @@ export function ImageGrid({
|
|||
cropHeight={GAP}
|
||||
attachment={attachments[1]}
|
||||
url={getThumbnailUrl(attachments[1])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
</div>
|
||||
|
@ -326,7 +388,9 @@ export function ImageGrid({
|
|||
cropWidth={GAP}
|
||||
attachment={attachments[2]}
|
||||
url={getThumbnailUrl(attachments[2])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
|
@ -342,11 +406,15 @@ export function ImageGrid({
|
|||
width={150}
|
||||
attachment={attachments[3]}
|
||||
url={getThumbnailUrl(attachments[3])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{detailPill}
|
||||
{downloadPill}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -372,7 +440,9 @@ export function ImageGrid({
|
|||
width={150}
|
||||
cropWidth={GAP}
|
||||
url={getThumbnailUrl(attachments[0])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
|
@ -386,7 +456,9 @@ export function ImageGrid({
|
|||
width={150}
|
||||
attachment={attachments[1]}
|
||||
url={getThumbnailUrl(attachments[1])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
</div>
|
||||
|
@ -405,7 +477,9 @@ export function ImageGrid({
|
|||
cropWidth={GAP}
|
||||
attachment={attachments[2]}
|
||||
url={getThumbnailUrl(attachments[2])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
|
@ -421,7 +495,9 @@ export function ImageGrid({
|
|||
cropWidth={GAP}
|
||||
attachment={attachments[3]}
|
||||
url={getThumbnailUrl(attachments[3])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={cancelDownload}
|
||||
startDownload={downloadPill ? undefined : startDownload}
|
||||
onError={onError}
|
||||
/>
|
||||
<Image
|
||||
|
@ -439,11 +515,51 @@ export function ImageGrid({
|
|||
overlayText={moreMessagesOverlayText}
|
||||
attachment={attachments[4]}
|
||||
url={getThumbnailUrl(attachments[4])}
|
||||
onClick={onClick}
|
||||
showVisualAttachment={showVisualAttachment}
|
||||
cancelDownload={undefined}
|
||||
startDownload={undefined}
|
||||
onError={onError}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{detailPill}
|
||||
{downloadPill}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function renderDownloadPill({
|
||||
attachments,
|
||||
i18n,
|
||||
startDownloadClick,
|
||||
startDownloadKeyDown,
|
||||
}: {
|
||||
attachments: ReadonlyArray<AttachmentForUIType>;
|
||||
i18n: LocalizerType;
|
||||
startDownloadClick: (event: React.MouseEvent) => void;
|
||||
startDownloadKeyDown: (event: React.KeyboardEvent<HTMLButtonElement>) => void;
|
||||
}): JSX.Element | null {
|
||||
const downloadedOrPending = attachments.some(
|
||||
attachment => attachment.path || attachment.pending
|
||||
);
|
||||
if (downloadedOrPending) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="module-image-grid__download-pill"
|
||||
aria-label={i18n('icu:startDownload')}
|
||||
onClick={startDownloadClick}
|
||||
onKeyDown={startDownloadKeyDown}
|
||||
>
|
||||
<div className="module-image-grid__download_pill__icon-wrapper">
|
||||
<div className="module-image-grid__download_pill__download-icon" />
|
||||
</div>
|
||||
<div className="module-image-grid__download_pill__text-wrapper">
|
||||
{i18n('icu:downloadNItems', { count: attachments.length })}
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue