Use streams to download attachments directly to disk
Co-authored-by: trevor-signal <131492920+trevor-signal@users.noreply.github.com>
This commit is contained in:
parent
2da49456c6
commit
99b2bc304e
48 changed files with 2297 additions and 356 deletions
|
@ -284,6 +284,7 @@ export type PropsData = {
|
|||
reactions?: ReactionViewerProps['reactions'];
|
||||
|
||||
deletedForEveryone?: boolean;
|
||||
attachmentDroppedDueToSize?: boolean;
|
||||
|
||||
canDeleteForEveryone: boolean;
|
||||
isBlocked: boolean;
|
||||
|
@ -565,6 +566,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
private getMetadataPlacement(
|
||||
{
|
||||
attachments,
|
||||
attachmentDroppedDueToSize,
|
||||
deletedForEveryone,
|
||||
direction,
|
||||
expirationLength,
|
||||
|
@ -599,12 +601,16 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
return MetadataPlacement.Bottom;
|
||||
}
|
||||
|
||||
if (!text && !deletedForEveryone) {
|
||||
if (!text && !deletedForEveryone && !attachmentDroppedDueToSize) {
|
||||
return isAudio(attachments)
|
||||
? MetadataPlacement.RenderedByMessageAudioComponent
|
||||
: MetadataPlacement.Bottom;
|
||||
}
|
||||
|
||||
if (!text && attachmentDroppedDueToSize) {
|
||||
return MetadataPlacement.InlineWithText;
|
||||
}
|
||||
|
||||
if (this.canRenderStickerLikeEmoji()) {
|
||||
return MetadataPlacement.Bottom;
|
||||
}
|
||||
|
@ -796,6 +802,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
const {
|
||||
attachmentDroppedDueToSize,
|
||||
deletedForEveryone,
|
||||
direction,
|
||||
expirationLength,
|
||||
|
@ -822,11 +829,14 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
direction={direction}
|
||||
expirationLength={expirationLength}
|
||||
expirationTimestamp={expirationTimestamp}
|
||||
hasText={Boolean(text)}
|
||||
hasText={Boolean(text || attachmentDroppedDueToSize)}
|
||||
i18n={i18n}
|
||||
id={id}
|
||||
isEditedMessage={isEditedMessage}
|
||||
isInline={isInline}
|
||||
isOutlineOnlyBubble={
|
||||
deletedForEveryone || (attachmentDroppedDueToSize && !text)
|
||||
}
|
||||
isShowingImage={this.isShowingImage()}
|
||||
isSticker={isStickerLike}
|
||||
isTapToViewExpired={isTapToViewExpired}
|
||||
|
@ -878,6 +888,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
public renderAttachment(): JSX.Element | null {
|
||||
const {
|
||||
attachments,
|
||||
attachmentDroppedDueToSize,
|
||||
conversationId,
|
||||
direction,
|
||||
expirationLength,
|
||||
|
@ -912,7 +923,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
const firstAttachment = attachments[0];
|
||||
|
||||
// For attachments which aren't full-frame
|
||||
const withContentBelow = Boolean(text);
|
||||
const withContentBelow = Boolean(text || attachmentDroppedDueToSize);
|
||||
const withContentAbove = Boolean(quote) || this.shouldRenderAuthor();
|
||||
const displayImage = canDisplayImage(attachments);
|
||||
|
||||
|
@ -1274,6 +1285,62 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
public renderAttachmentTooBig(): JSX.Element | null {
|
||||
const {
|
||||
attachments,
|
||||
attachmentDroppedDueToSize,
|
||||
direction,
|
||||
i18n,
|
||||
quote,
|
||||
shouldCollapseAbove,
|
||||
shouldCollapseBelow,
|
||||
text,
|
||||
} = this.props;
|
||||
const { metadataWidth } = this.state;
|
||||
|
||||
if (!attachmentDroppedDueToSize) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const labelText = attachments?.length
|
||||
? i18n('icu:message--attachmentTooBig--multiple')
|
||||
: i18n('icu:message--attachmentTooBig--one');
|
||||
|
||||
const isContentAbove = quote || attachments?.length;
|
||||
const isContentBelow = Boolean(text);
|
||||
const willCollapseAbove = shouldCollapseAbove && !isContentAbove;
|
||||
const willCollapseBelow = shouldCollapseBelow && !isContentBelow;
|
||||
|
||||
const maybeSpacer = text
|
||||
? undefined
|
||||
: this.getMetadataPlacement() === MetadataPlacement.InlineWithText && (
|
||||
<MessageTextMetadataSpacer metadataWidth={metadataWidth} />
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'module-message__attachment-too-big',
|
||||
isContentAbove
|
||||
? 'module-message__attachment-too-big--content-above'
|
||||
: null,
|
||||
isContentBelow
|
||||
? 'module-message__attachment-too-big--content-below'
|
||||
: null,
|
||||
willCollapseAbove
|
||||
? `module-message__attachment-too-big--collapse-above--${direction}`
|
||||
: null,
|
||||
willCollapseBelow
|
||||
? `module-message__attachment-too-big--collapse-below--${direction}`
|
||||
: null
|
||||
)}
|
||||
>
|
||||
{labelText}
|
||||
{maybeSpacer}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
public renderGiftBadge(): JSX.Element | null {
|
||||
const { conversationTitle, direction, getPreferredBadge, giftBadge, i18n } =
|
||||
this.props;
|
||||
|
@ -1757,6 +1824,19 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
private getContents(): string | undefined {
|
||||
const { deletedForEveryone, direction, i18n, status, text } = this.props;
|
||||
|
||||
if (deletedForEveryone) {
|
||||
return i18n('icu:message--deletedForEveryone');
|
||||
}
|
||||
if (direction === 'incoming' && status === 'error') {
|
||||
return i18n('icu:incomingError');
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public renderText(): JSX.Element | null {
|
||||
const {
|
||||
bodyRanges,
|
||||
|
@ -1772,17 +1852,12 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
showConversation,
|
||||
showSpoiler,
|
||||
status,
|
||||
text,
|
||||
|
||||
textAttachment,
|
||||
} = this.props;
|
||||
const { metadataWidth } = this.state;
|
||||
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
const contents = deletedForEveryone
|
||||
? i18n('icu:message--deletedForEveryone')
|
||||
: direction === 'incoming' && status === 'error'
|
||||
? i18n('icu:incomingError')
|
||||
: text;
|
||||
const contents = this.getContents();
|
||||
|
||||
if (!contents) {
|
||||
return null;
|
||||
|
@ -2296,7 +2371,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
public renderContents(): JSX.Element | null {
|
||||
const { giftBadge, isTapToView, deletedForEveryone } = this.props;
|
||||
const { deletedForEveryone, giftBadge, isTapToView } = this.props;
|
||||
|
||||
if (deletedForEveryone) {
|
||||
return (
|
||||
|
@ -2326,6 +2401,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
{this.renderStoryReplyContext()}
|
||||
{this.renderAttachment()}
|
||||
{this.renderPreview()}
|
||||
{this.renderAttachmentTooBig()}
|
||||
{this.renderPayment()}
|
||||
{this.renderEmbeddedContact()}
|
||||
{this.renderText()}
|
||||
|
@ -2534,6 +2610,7 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
public renderContainer(): JSX.Element {
|
||||
const {
|
||||
attachments,
|
||||
attachmentDroppedDueToSize,
|
||||
conversationColor,
|
||||
customColor,
|
||||
deletedForEveryone,
|
||||
|
@ -2597,7 +2674,12 @@ export class Message extends React.PureComponent<Props, State> {
|
|||
const containerStyles = {
|
||||
width: shouldUseWidth ? width : undefined,
|
||||
};
|
||||
if (!isStickerLike && !deletedForEveryone && direction === 'outgoing') {
|
||||
if (
|
||||
!isStickerLike &&
|
||||
!deletedForEveryone &&
|
||||
!(attachmentDroppedDueToSize && !text) &&
|
||||
direction === 'outgoing'
|
||||
) {
|
||||
Object.assign(containerStyles, getCustomColorStyle(customColor));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue