Fix undownloadable attachment check to require download error

This commit is contained in:
ayumi-signal 2025-01-17 09:34:22 -08:00 committed by GitHub
parent 7a6b5ffe09
commit 1bab28239a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 64 additions and 37 deletions

View file

@ -14,8 +14,8 @@ import type {
} from '../../types/Attachment'; } from '../../types/Attachment';
import { import {
defaultBlurHash, defaultBlurHash,
isDownloadable,
isIncremental, isIncremental,
isPermanentlyUndownloadable,
isReadyToView, isReadyToView,
} from '../../types/Attachment'; } from '../../types/Attachment';
import { ProgressCircle } from '../ProgressCircle'; import { ProgressCircle } from '../ProgressCircle';
@ -191,10 +191,7 @@ export function Image({
); );
const startDownloadButton = const startDownloadButton =
startDownload && !attachment.path && !attachment.pending && !isIncremental(attachment) ? (
!attachment.path &&
!attachment.pending &&
!isIncremental(attachment) ? (
<button <button
type="button" type="button"
className="module-image__overlay-circle" className="module-image__overlay-circle"
@ -207,6 +204,25 @@ export function Image({
</button> </button>
) : undefined; ) : undefined;
const isUndownloadable = isPermanentlyUndownloadable(attachment);
// eslint-disable-next-line no-nested-ternary
const startDownloadOrUnavailableButton = startDownload ? (
isUndownloadable ? (
<button
type="button"
className="module-image__overlay-circle module-image__overlay-circle--undownloadable"
aria-label={i18n('icu:mediaNoLongerAvailable')}
onClick={undownloadableClick}
tabIndex={tabIndex}
>
<div className="module-image__undownloadable-icon" />
</button>
) : (
startDownloadButton
)
) : null;
const spinner = const spinner =
isIncremental(attachment) || !cancelDownload isIncremental(attachment) || !cancelDownload
? undefined ? undefined
@ -218,8 +234,6 @@ export function Image({
tabIndex, tabIndex,
}); });
const isMediaDownloadable = isDownloadable(attachment);
return ( return (
<div <div
className={classNames( className={classNames(
@ -235,19 +249,7 @@ export function Image({
}} }}
> >
{imageOrBlurHash} {imageOrBlurHash}
{isMediaDownloadable ? ( {startDownloadOrUnavailableButton}
startDownloadButton
) : (
<button
type="button"
className="module-image__overlay-circle module-image__overlay-circle--undownloadable"
aria-label={i18n('icu:mediaNoLongerAvailable')}
onClick={undownloadableClick}
tabIndex={tabIndex}
>
<div className="module-image__undownloadable-icon" />
</button>
)}
{spinner} {spinner}
{attachment.caption ? ( {attachment.caption ? (
@ -267,7 +269,7 @@ export function Image({
/> />
) : null} ) : null}
{(attachment.path || isIncremental(attachment)) && {(attachment.path || isIncremental(attachment)) &&
isMediaDownloadable && !isUndownloadable &&
playIconOverlay ? ( playIconOverlay ? (
<div className="module-image__overlay-circle"> <div className="module-image__overlay-circle">
<div className="module-image__play-icon" /> <div className="module-image__play-icon" />
@ -290,9 +292,7 @@ export function Image({
style={curveStyles} style={curveStyles}
/> />
) : null} ) : null}
{showVisualAttachment && {showVisualAttachment && isReadyToView(attachment) ? (
isReadyToView(attachment) &&
isMediaDownloadable ? (
<button <button
type="button" type="button"
className={classNames('module-image__border-overlay', { className={classNames('module-image__border-overlay', {

View file

@ -16,6 +16,7 @@ import {
getUrl, getUrl,
isDownloadable, isDownloadable,
isIncremental, isIncremental,
isPermanentlyUndownloadable,
isVideoAttachment, isVideoAttachment,
} from '../../types/Attachment'; } from '../../types/Attachment';
@ -157,6 +158,14 @@ export function ImageGrid({
[startDownload] [startDownload]
); );
const showAttachmentOrNoLongerAvailableToast = React.useCallback(
attachmentIndex =>
isPermanentlyUndownloadable(attachments[attachmentIndex])
? showMediaNoLongerAvailableToast
: showVisualAttachment,
[attachments, showVisualAttachment, showMediaNoLongerAvailableToast]
);
if (!attachments || !attachments.length) { if (!attachments || !attachments.length) {
return null; return null;
} }
@ -215,7 +224,7 @@ export function ImageGrid({
} }
tabIndex={tabIndex} tabIndex={tabIndex}
showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast} showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast}
showVisualAttachment={showVisualAttachment} showVisualAttachment={showAttachmentOrNoLongerAvailableToast(0)}
cancelDownload={cancelDownload} cancelDownload={cancelDownload}
startDownload={startDownload} startDownload={startDownload}
onError={onError} onError={onError}
@ -244,7 +253,7 @@ export function ImageGrid({
cropWidth={GAP} cropWidth={GAP}
url={getThumbnailUrl(attachments[0])} url={getThumbnailUrl(attachments[0])}
showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast} showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast}
showVisualAttachment={showVisualAttachment} showVisualAttachment={showAttachmentOrNoLongerAvailableToast(0)}
cancelDownload={cancelDownload} cancelDownload={cancelDownload}
startDownload={downloadPill ? undefined : startDownload} startDownload={downloadPill ? undefined : startDownload}
onError={onError} onError={onError}
@ -264,7 +273,7 @@ export function ImageGrid({
attachment={attachments[1]} attachment={attachments[1]}
url={getThumbnailUrl(attachments[1])} url={getThumbnailUrl(attachments[1])}
showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast} showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast}
showVisualAttachment={showVisualAttachment} showVisualAttachment={showAttachmentOrNoLongerAvailableToast(1)}
cancelDownload={cancelDownload} cancelDownload={cancelDownload}
startDownload={downloadPill ? undefined : startDownload} startDownload={downloadPill ? undefined : startDownload}
onError={onError} onError={onError}
@ -294,7 +303,7 @@ export function ImageGrid({
cropWidth={GAP} cropWidth={GAP}
url={getUrl(attachments[0])} url={getUrl(attachments[0])}
showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast} showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast}
showVisualAttachment={showVisualAttachment} showVisualAttachment={showAttachmentOrNoLongerAvailableToast(0)}
cancelDownload={cancelDownload} cancelDownload={cancelDownload}
startDownload={downloadPill ? undefined : startDownload} startDownload={downloadPill ? undefined : startDownload}
onError={onError} onError={onError}
@ -313,7 +322,7 @@ export function ImageGrid({
playIconOverlay={isVideoAttachment(attachments[1])} playIconOverlay={isVideoAttachment(attachments[1])}
url={getThumbnailUrl(attachments[1])} url={getThumbnailUrl(attachments[1])}
showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast} showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast}
showVisualAttachment={showVisualAttachment} showVisualAttachment={showAttachmentOrNoLongerAvailableToast(1)}
cancelDownload={cancelDownload} cancelDownload={cancelDownload}
startDownload={downloadPill ? undefined : startDownload} startDownload={downloadPill ? undefined : startDownload}
onError={onError} onError={onError}
@ -332,7 +341,7 @@ export function ImageGrid({
playIconOverlay={isVideoAttachment(attachments[2])} playIconOverlay={isVideoAttachment(attachments[2])}
url={getThumbnailUrl(attachments[2])} url={getThumbnailUrl(attachments[2])}
showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast} showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast}
showVisualAttachment={showVisualAttachment} showVisualAttachment={showAttachmentOrNoLongerAvailableToast(2)}
cancelDownload={cancelDownload} cancelDownload={cancelDownload}
startDownload={downloadPill ? undefined : startDownload} startDownload={downloadPill ? undefined : startDownload}
onError={onError} onError={onError}
@ -364,7 +373,7 @@ export function ImageGrid({
cropWidth={GAP} cropWidth={GAP}
url={getThumbnailUrl(attachments[0])} url={getThumbnailUrl(attachments[0])}
showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast} showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast}
showVisualAttachment={showVisualAttachment} showVisualAttachment={showAttachmentOrNoLongerAvailableToast(0)}
cancelDownload={cancelDownload} cancelDownload={cancelDownload}
startDownload={downloadPill ? undefined : startDownload} startDownload={downloadPill ? undefined : startDownload}
onError={onError} onError={onError}
@ -383,7 +392,7 @@ export function ImageGrid({
attachment={attachments[1]} attachment={attachments[1]}
url={getThumbnailUrl(attachments[1])} url={getThumbnailUrl(attachments[1])}
showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast} showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast}
showVisualAttachment={showVisualAttachment} showVisualAttachment={showAttachmentOrNoLongerAvailableToast(1)}
cancelDownload={cancelDownload} cancelDownload={cancelDownload}
startDownload={downloadPill ? undefined : startDownload} startDownload={downloadPill ? undefined : startDownload}
onError={onError} onError={onError}
@ -405,7 +414,7 @@ export function ImageGrid({
attachment={attachments[2]} attachment={attachments[2]}
url={getThumbnailUrl(attachments[2])} url={getThumbnailUrl(attachments[2])}
showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast} showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast}
showVisualAttachment={showVisualAttachment} showVisualAttachment={showAttachmentOrNoLongerAvailableToast(2)}
cancelDownload={cancelDownload} cancelDownload={cancelDownload}
startDownload={downloadPill ? undefined : startDownload} startDownload={downloadPill ? undefined : startDownload}
onError={onError} onError={onError}
@ -424,7 +433,7 @@ export function ImageGrid({
attachment={attachments[3]} attachment={attachments[3]}
url={getThumbnailUrl(attachments[3])} url={getThumbnailUrl(attachments[3])}
showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast} showMediaNoLongerAvailableToast={showMediaNoLongerAvailableToast}
showVisualAttachment={showVisualAttachment} showVisualAttachment={showAttachmentOrNoLongerAvailableToast(3)}
cancelDownload={cancelDownload} cancelDownload={cancelDownload}
startDownload={downloadPill ? undefined : startDownload} startDownload={downloadPill ? undefined : startDownload}
onError={onError} onError={onError}

View file

@ -70,7 +70,7 @@ import {
isVideo, isVideo,
isGIF, isGIF,
isPlayed, isPlayed,
isDownloadable, isPermanentlyUndownloadable,
} from '../../types/Attachment'; } from '../../types/Attachment';
import type { EmbeddedContactType } from '../../types/EmbeddedContact'; import type { EmbeddedContactType } from '../../types/EmbeddedContact';
@ -2563,6 +2563,7 @@ export class Message extends React.PureComponent<Props, State> {
showLightbox, showLightbox,
showExpiredIncomingTapToViewToast, showExpiredIncomingTapToViewToast,
showExpiredOutgoingTapToViewToast, showExpiredOutgoingTapToViewToast,
showMediaNoLongerAvailableToast,
} = this.props; } = this.props;
const { imageBroken } = this.state; const { imageBroken } = this.state;
@ -2573,6 +2574,18 @@ export class Message extends React.PureComponent<Props, State> {
return; return;
} }
if (
attachments &&
attachments.length > 0 &&
isPermanentlyUndownloadable(attachments[0])
) {
event.preventDefault();
event.stopPropagation();
showMediaNoLongerAvailableToast();
return;
}
if (isTapToView) { if (isTapToView) {
if (isAttachmentPending) { if (isAttachmentPending) {
log.info( log.info(
@ -2610,8 +2623,7 @@ export class Message extends React.PureComponent<Props, State> {
attachments && attachments &&
attachments.length > 0 && attachments.length > 0 &&
!isAttachmentPending && !isAttachmentPending &&
!isDownloaded(attachments[0]) && !isDownloaded(attachments[0])
isDownloadable(attachments[0])
) { ) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();

View file

@ -1268,6 +1268,12 @@ export function isDownloadable(attachment: AttachmentType): boolean {
); );
} }
export function isPermanentlyUndownloadable(
attachment: AttachmentType
): boolean {
return Boolean(!isDownloadable(attachment) && attachment.error);
}
export function isAttachmentLocallySaved( export function isAttachmentLocallySaved(
attachment: AttachmentType attachment: AttachmentType
): attachment is LocallySavedAttachment { ): attachment is LocallySavedAttachment {