From 9fa3359477b37adf74013279dc25425879c3bb4e Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Mon, 22 Mar 2021 11:51:53 -0700 Subject: [PATCH] Mark attachment as corrupted if audio load failed Sending corrupted audio should not leave user with non-functional UI. Mark attachment as corrupted and show generic attachment UI for it instead. --- .../conversation/Message.stories.tsx | 1 + ts/components/conversation/Message.tsx | 12 ++++++ ts/components/conversation/MessageAudio.tsx | 19 ++++++++- .../conversation/MessageDetail.stories.tsx | 1 + ts/components/conversation/Quote.stories.tsx | 1 + .../conversation/Timeline.stories.tsx | 1 + .../conversation/TimelineItem.stories.tsx | 1 + ts/models/messages.ts | 41 +++++++++++++++++++ ts/state/smart/MessageAudio.tsx | 1 + ts/types/Attachment.ts | 2 + ts/util/lint/exceptions.json | 6 +-- ts/views/conversation_view.ts | 17 ++++++++ 12 files changed, 98 insertions(+), 5 deletions(-) diff --git a/ts/components/conversation/Message.stories.tsx b/ts/components/conversation/Message.stories.tsx index 81b4a69e5..0d02671d2 100644 --- a/ts/components/conversation/Message.stories.tsx +++ b/ts/components/conversation/Message.stories.tsx @@ -111,6 +111,7 @@ const createProps = (overrideProps: Partial = {}): Props => ({ isTapToViewError: overrideProps.isTapToViewError, isTapToViewExpired: overrideProps.isTapToViewExpired, kickOffAttachmentDownload: action('kickOffAttachmentDownload'), + markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'), openConversation: action('openConversation'), openLink: action('openLink'), previews: overrideProps.previews || [], diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index fc4dc740f..936a6cd03 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -90,6 +90,7 @@ export type AudioAttachmentProps = { withContentBelow: boolean; kickOffAttachmentDownload(): void; + onCorrupted(): void; }; export type PropsData = { @@ -185,6 +186,10 @@ export type PropsActions = { attachment: AttachmentType; messageId: string; }) => void; + markAttachmentAsCorrupted: (options: { + attachment: AttachmentType; + messageId: string; + }) => void; showVisualAttachment: (options: { attachment: AttachmentType; messageId: string; @@ -686,6 +691,7 @@ export class Message extends React.PureComponent { i18n, id, kickOffAttachmentDownload, + markAttachmentAsCorrupted, quote, showVisualAttachment, isSticker, @@ -773,6 +779,12 @@ export class Message extends React.PureComponent { messageId: id, }); }, + onCorrupted() { + markAttachmentAsCorrupted({ + attachment: firstAttachment, + messageId: id, + }); + }, }); } const { pending, fileName, fileSize, contentType } = firstAttachment; diff --git a/ts/components/conversation/MessageAudio.tsx b/ts/components/conversation/MessageAudio.tsx index 7f6861764..7da1ed422 100644 --- a/ts/components/conversation/MessageAudio.tsx +++ b/ts/components/conversation/MessageAudio.tsx @@ -25,6 +25,7 @@ export type Props = { buttonRef: React.RefObject; kickOffAttachmentDownload(): void; + onCorrupted(): void; activeAudioID: string | undefined; setActiveAudioID: (id: string | undefined) => void; @@ -208,6 +209,7 @@ export const MessageAudio: React.FC = (props: Props) => { buttonRef, kickOffAttachmentDownload, + onCorrupted, audio, audioContext, @@ -275,14 +277,27 @@ export const MessageAudio: React.FC = (props: Props) => { setPeaks(newPeaks); setDuration(Math.max(newDuration, 1e-23)); } catch (err) { - window.log.error('MessageAudio: loadAudio error', err); + window.log.error( + 'MessageAudio: loadAudio error, marking as corrupted', + err + ); + + onCorrupted(); } })(); return () => { canceled = true; }; - }, [attachment, audioContext, setDuration, setPeaks, state, waveformCache]); + }, [ + attachment, + audioContext, + setDuration, + setPeaks, + onCorrupted, + state, + waveformCache, + ]); // This effect attaches/detaches event listeners to the global