Introduce smaller incoming size limit for text attachments

This commit is contained in:
Scott Nonnenberg 2023-12-18 10:14:59 -08:00 committed by GitHub
parent 8c71ed2590
commit 5e733059b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 31 deletions

View file

@ -2891,6 +2891,10 @@
"messageformat": "Read more", "messageformat": "Read more",
"description": "When a message is too long this is the affordance to expand the message" "description": "When a message is too long this is the affordance to expand the message"
}, },
"icu:MessageBody--message-too-long": {
"messageformat": "Message too long to display more",
"description": "When an incoming message is too long, and we refused to download it"
},
"icu:Message--unsupported-message": { "icu:Message--unsupported-message": {
"messageformat": "{contact} sent you a message that can't be processed or displayed because it uses a new Signal feature." "messageformat": "{contact} sent you a message that can't be processed or displayed because it uses a new Signal feature."
}, },

View file

@ -19,6 +19,10 @@
} }
} }
&__message-too-long {
font-weight: bold;
}
&__at-mention { &__at-mention {
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;

View file

@ -35,7 +35,8 @@ export type ConfigKeyType =
| 'global.groupsv2.groupSizeHardLimit' | 'global.groupsv2.groupSizeHardLimit'
| 'global.groupsv2.maxGroupSize' | 'global.groupsv2.maxGroupSize'
| 'global.nicknames.max' | 'global.nicknames.max'
| 'global.nicknames.min'; | 'global.nicknames.min'
| 'global.textAttachmentLimitBytes';
type ConfigValueType = { type ConfigValueType = {
name: ConfigKeyType; name: ConfigKeyType;

View file

@ -118,6 +118,17 @@ export function TextPending(): JSX.Element {
return <MessageBody {...props} />; return <MessageBody {...props} />;
} }
export function MessageTooLong(): JSX.Element {
const props = createProps({
text: 'Check out https://www.signal.org',
textAttachment: {
wasTooBig: true,
},
});
return <MessageBody {...props} />;
}
export function Mention(): JSX.Element { export function Mention(): JSX.Element {
const props = createProps({ const props = createProps({
bodyRanges: [ bodyRanges: [

View file

@ -33,7 +33,10 @@ export type Props = {
renderLocation: RenderLocation; renderLocation: RenderLocation;
showConversation?: ShowConversationType; showConversation?: ShowConversationType;
text: string; text: string;
textAttachment?: Pick<AttachmentType, 'pending' | 'digest' | 'key'>; textAttachment?: Pick<
AttachmentType,
'pending' | 'digest' | 'key' | 'wasTooBig'
>;
}; };
/** /**
@ -59,19 +62,36 @@ export function MessageBody({
text, text,
textAttachment, textAttachment,
}: Props): JSX.Element { }: Props): JSX.Element {
const hasReadMore = Boolean(onIncreaseTextLength);
const shouldDisableLinks = disableLinks || !shouldLinkifyMessage(text); const shouldDisableLinks = disableLinks || !shouldLinkifyMessage(text);
const textWithSuffix = const textWithSuffix =
textAttachment?.pending || hasReadMore ? `${text}...` : text; textAttachment?.pending || onIncreaseTextLength || textAttachment?.wasTooBig
? `${text}...`
: text;
const sizeClass = disableJumbomoji ? undefined : getSizeClass(text); const sizeClass = disableJumbomoji ? undefined : getSizeClass(text);
let pendingContent: React.ReactNode; let endNotification: React.ReactNode;
if (hasReadMore) { if (onIncreaseTextLength) {
pendingContent = null; endNotification = (
<button
className="MessageBody__read-more"
onClick={() => {
onIncreaseTextLength();
}}
onKeyDown={(ev: KeyboardEvent) => {
if (ev.key === 'Space' || ev.key === 'Enter') {
onIncreaseTextLength();
}
}}
tabIndex={0}
type="button"
>
{' '}
{i18n('icu:MessageBody--read-more')}
</button>
);
} else if (textAttachment?.pending) { } else if (textAttachment?.pending) {
pendingContent = ( endNotification = (
<span className="MessageBody__highlight"> {i18n('icu:downloading')}</span> <span className="MessageBody__highlight"> {i18n('icu:downloading')}</span>
); );
} else if ( } else if (
@ -79,7 +99,7 @@ export function MessageBody({
canBeDownloaded(textAttachment) && canBeDownloaded(textAttachment) &&
kickOffBodyDownload kickOffBodyDownload
) { ) {
pendingContent = ( endNotification = (
<span> <span>
{' '} {' '}
<button <button
@ -99,8 +119,14 @@ export function MessageBody({
</button> </button>
</span> </span>
); );
} else if (textAttachment?.wasTooBig) {
endNotification = (
<span className="MessageBody__message-too-long">
{' '}
{i18n('icu:MessageBody--message-too-long')}
</span>
);
} }
return ( return (
<span> <span>
{author && ( {author && (
@ -135,25 +161,7 @@ export function MessageBody({
textLength={text.length} textLength={text.length}
/> />
{pendingContent} {endNotification}
{onIncreaseTextLength ? (
<button
className="MessageBody__read-more"
onClick={() => {
onIncreaseTextLength();
}}
onKeyDown={(ev: KeyboardEvent) => {
if (ev.key === 'Space' || ev.key === 'Enter') {
onIncreaseTextLength();
}
}}
tabIndex={0}
type="button"
>
{' '}
{i18n('icu:MessageBody--read-more')}
</button>
) : null}
</span> </span>
); );
} }

View file

@ -29,6 +29,7 @@ import * as log from '../logging/log';
import { import {
KIBIBYTE, KIBIBYTE,
getMaximumIncomingAttachmentSizeInKb, getMaximumIncomingAttachmentSizeInKb,
getMaximumIncomingTextAttachmentSizeInKb,
} from '../types/AttachmentSize'; } from '../types/AttachmentSize';
const { const {
@ -281,14 +282,23 @@ async function _runJob(job?: AttachmentDownloadJobType): Promise<void> {
let downloaded: AttachmentType | null = null; let downloaded: AttachmentType | null = null;
try { try {
const { size } = attachment;
const maxInKib = getMaximumIncomingAttachmentSizeInKb(getValue); const maxInKib = getMaximumIncomingAttachmentSizeInKb(getValue);
const maxTextAttachmentSizeInKib =
getMaximumIncomingTextAttachmentSizeInKb(getValue);
const { size } = attachment;
const sizeInKib = size / KIBIBYTE; const sizeInKib = size / KIBIBYTE;
if (!size || sizeInKib > maxInKib) { if (!size || sizeInKib > maxInKib) {
throw new AttachmentSizeError( throw new AttachmentSizeError(
`Attachment Job ${id}: Attachment was ${sizeInKib}kib, max is ${maxInKib}kib` `Attachment Job ${id}: Attachment was ${sizeInKib}kib, max is ${maxInKib}kib`
); );
} }
if (type === 'long-message' && sizeInKib > maxTextAttachmentSizeInKib) {
throw new AttachmentSizeError(
`Attachment Job ${id}: Text attachment was ${sizeInKib}kib, max is ${maxTextAttachmentSizeInKib}kib`
);
}
await _addAttachmentToMessage( await _addAttachmentToMessage(
message, message,

View file

@ -43,6 +43,22 @@ export const getMaximumIncomingAttachmentSizeInKb = (
} }
}; };
export const getMaximumIncomingTextAttachmentSizeInKb = (
getValue: typeof RemoteConfig.getValue
): number => {
try {
return (
parseIntOrThrow(
getValue('global.textAttachmentLimitBytes'),
'getMaximumIncomingTextAttachmentSizeInKb'
) / KIBIBYTE
);
} catch (_error) {
// TODO: DESKTOP-6314. We're not gonna log until the new flag is fully deployed
return KIBIBYTE * 5;
}
};
export function getRenderDetailsForLimit(limitKb: number): { export function getRenderDetailsForLimit(limitKb: number): {
limit: number; limit: number;
units: string; units: string;