signal-desktop/ts/util/attachments.ts

97 lines
3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { blobToArrayBuffer } from 'blob-util';
import * as log from '../logging/log';
import { scaleImageToLevel } from './scaleImageToLevel';
import { dropNull } from './dropNull';
import type {
AttachmentType,
UploadedAttachmentType,
} from '../types/Attachment';
import { canBeTranscoded } from '../types/Attachment';
import * as Errors from '../types/errors';
import * as Bytes from '../Bytes';
// All outgoing images go through handleImageAttachment before being sent and thus have
// already been scaled to high-quality level, stripped of exif data, and saved. This
// should be called just before message send to downscale the attachment further if
// needed.
export const downscaleOutgoingAttachment = async (
attachment: AttachmentType
): Promise<AttachmentType> => {
if (!canBeTranscoded(attachment)) {
return attachment;
}
let scaleTarget: string | Blob;
const { data, path, size } = attachment;
if (data) {
scaleTarget = new Blob([data], {
type: attachment.contentType,
});
} else {
if (!path) {
return attachment;
}
scaleTarget = window.Signal.Migrations.getAbsoluteAttachmentPath(path);
}
try {
const { blob: xcodedDataBlob } = await scaleImageToLevel({
fileOrBlobOrURL: scaleTarget,
contentType: attachment.contentType,
size,
highQuality: false,
});
const xcodedDataArrayBuffer = await blobToArrayBuffer(xcodedDataBlob);
// IMPORTANT: We overwrite the existing `data` `Uint8Array` losing the original
// image data. Ideally, wed preserve the original image data for users who want to
// retain it but due to reports of data loss, we dont want to overburden IndexedDB
// by potentially doubling stored image data.
// See: https://github.com/signalapp/Signal-Desktop/issues/1589
// We also clear out the attachment path because we're changing
// the attachment data so it no longer matches the old path.
// Path and data should always be in agreement.
const xcodedAttachment = {
...attachment,
data: new Uint8Array(xcodedDataArrayBuffer),
size: xcodedDataArrayBuffer.byteLength,
path: undefined,
};
return xcodedAttachment;
} catch (error: unknown) {
const errorString = Errors.toLogFormat(error);
log.error(
'downscaleOutgoingAttachment: Failed to scale attachment',
errorString
);
return attachment;
}
};
export type CdnFieldsType = Pick<
AttachmentType,
'cdnId' | 'cdnKey' | 'cdnNumber' | 'key' | 'digest' | 'plaintextHash'
>;
export function copyCdnFields(
uploaded?: UploadedAttachmentType
): CdnFieldsType {
if (!uploaded) {
return {};
}
return {
cdnId: dropNull(uploaded.cdnId)?.toString(),
cdnKey: uploaded.cdnKey,
cdnNumber: dropNull(uploaded.cdnNumber),
key: Bytes.toBase64(uploaded.key),
digest: Bytes.toBase64(uploaded.digest),
plaintextHash: uploaded.plaintextHash,
};
}