@@ -165,5 +93,9 @@ export function AttachmentStatusIcon({
);
}
- return
{children}
;
+ if (status.state === 'ReadyToShow') {
+ return
{children}
;
+ }
+
+ throw missingCaseError(status);
}
diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx
index 675bd084f8b..a60156b52d9 100644
--- a/ts/components/conversation/Message.tsx
+++ b/ts/components/conversation/Message.tsx
@@ -2869,14 +2869,17 @@ export class Message extends React.PureComponent
{
: null
)}
>
-
- {this.renderTapToViewIcon()}
-
+ {isExpired || firstAttachment == null ? (
+ this.renderTapToViewIcon()
+ ) : (
+
+ {this.renderTapToViewIcon()}
+
+ )}
{content}
);
diff --git a/ts/components/conversation/contactUtil.tsx b/ts/components/conversation/contactUtil.tsx
index 513c713f602..51146e96c98 100644
--- a/ts/components/conversation/contactUtil.tsx
+++ b/ts/components/conversation/contactUtil.tsx
@@ -28,23 +28,31 @@ export function renderAvatar({
const avatarUrl = avatar && avatar.avatar && avatar.avatar.path;
const title = getName(contact) || '';
+ const fallback = (
+
+ );
+
+ const attachment = avatar?.avatar;
+ if (attachment == null) {
+ return fallback;
+ }
return (
-
+ {fallback}
);
}
diff --git a/ts/components/conversation/media-gallery/AttachmentSection.tsx b/ts/components/conversation/media-gallery/AttachmentSection.tsx
index 3e5d0fa57a7..30a5e67370e 100644
--- a/ts/components/conversation/media-gallery/AttachmentSection.tsx
+++ b/ts/components/conversation/media-gallery/AttachmentSection.tsx
@@ -8,6 +8,7 @@ import type { LocalizerType, ThemeType } from '../../../types/Util.js';
import type { MediaItemType } from '../../../types/MediaItem.js';
import { DocumentListItem } from './DocumentListItem.js';
import { MediaGridItem } from './MediaGridItem.js';
+import type { AttachmentStatusType } from '../../../hooks/useAttachmentStatus.js';
import { missingCaseError } from '../../../util/missingCaseError.js';
import { tw } from '../../../axo/tw.js';
@@ -37,9 +38,8 @@ export function AttachmentSection({
{mediaItems.map(mediaItem => {
const { message, index, attachment } = mediaItem;
- const onClick = (ev: React.MouseEvent) => {
- ev.preventDefault();
- onItemClick({ type, message, attachment });
+ const onClick = (state: AttachmentStatusType['state']) => {
+ onItemClick({ type, message, attachment, state });
};
return (
@@ -69,13 +69,13 @@ export function AttachmentSection({
{mediaItems.map(mediaItem => {
const { message, index, attachment } = mediaItem;
- const onClick = (ev: React.MouseEvent) => {
- ev.preventDefault();
- onItemClick({ type, message, attachment });
+ const onClick = (state: AttachmentStatusType['state']) => {
+ onItemClick({ type, message, attachment, state });
};
return (
;
+const { i18n } = window.SignalContext;
+
export function Multiple(): JSX.Element {
const items = createPreparedMediaItems(createRandomDocuments);
@@ -22,6 +24,7 @@ export function Multiple(): JSX.Element {
<>
{items.map(mediaItem => (
void;
+ onClick?: (status: AttachmentStatusType['state']) => void;
};
-export function DocumentListItem({ mediaItem, onClick }: Props): JSX.Element {
+export function DocumentListItem({
+ i18n,
+ mediaItem,
+ onClick,
+}: Props): JSX.Element {
const { attachment, message } = mediaItem;
const { fileName, size: fileSize } = attachment;
const timestamp = message.receivedAtMs || message.receivedAt;
+ let label: string;
+
+ const status = useAttachmentStatus(attachment);
+
+ const handleClick = useCallback(
+ (ev: React.MouseEvent) => {
+ ev.preventDefault();
+ onClick?.(status.state);
+ },
+ [onClick, status.state]
+ );
+
+ if (status.state === 'NeedsDownload') {
+ label = i18n('icu:downloadAttachment');
+ } else if (status.state === 'Downloading') {
+ label = i18n('icu:cancelDownload');
+ } else if (status.state === 'ReadyToShow') {
+ label = i18n('icu:startDownload');
+ } else {
+ throw missingCaseError(status);
+ }
+
+ let glyph: JSX.Element | undefined;
+ let button: JSX.Element | undefined;
+ if (status.state !== 'ReadyToShow') {
+ glyph = (
+ <>
+
+
+ >
+ );
+ button = (
+
+ {status.state === 'Downloading' && (
+
+ )}
+
+
+ );
+ }
+
return (