Alexander Zinchuk 3afcde3217 Initial commit
2021-04-09 14:11:51 +03:00

80 lines
2.4 KiB
TypeScript

import { ApiAttachment } from '../../../../api/types';
import { preloadImage, preloadVideo, createPosterForVideo } from '../../../../util/files';
const MAX_QUICK_VIDEO_SIZE = 10 * 1024 ** 2; // 10 MB
const MAX_QUICK_IMG_SIZE = 1280; // px
export default async function buildAttachment(
filename: string, blob: Blob, isQuick: boolean, options?: Partial<ApiAttachment>,
): Promise<ApiAttachment> {
const blobUrl = URL.createObjectURL(blob);
const { type: mimeType, size } = blob;
let quick;
let previewBlobUrl;
if (mimeType.startsWith('image/')) {
if (isQuick) {
const img = await preloadImage(blobUrl);
const { width, height } = img;
if (width > MAX_QUICK_IMG_SIZE || height > MAX_QUICK_IMG_SIZE || mimeType !== 'image/jpeg') {
const newBlob = await squeezeImage(img);
if (newBlob) {
URL.revokeObjectURL(blobUrl);
return buildAttachment(filename, newBlob, true, options);
} else {
return buildAttachment(filename, blob, false, options);
}
}
quick = { width, height };
} else {
previewBlobUrl = blobUrl;
}
} else if (mimeType.startsWith('video/')) {
// Videos < 10 MB are always sent in quick mode (in other clients).
// Quick mode for videos > 10 MB is not supported until client-side video squeezing is implemented.
if (size < MAX_QUICK_VIDEO_SIZE) {
const { videoWidth: width, videoHeight: height, duration } = await preloadVideo(blobUrl);
quick = { width, height, duration };
}
previewBlobUrl = await createPosterForVideo(blobUrl);
}
return {
blobUrl,
filename,
mimeType,
size,
quick,
previewBlobUrl,
...options,
};
}
function squeezeImage(img: HTMLImageElement): Promise<Blob | null> {
return new Promise((resolve) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d')!;
let { width, height } = img;
if (width > MAX_QUICK_IMG_SIZE || height > MAX_QUICK_IMG_SIZE) {
if (width >= height) {
height *= MAX_QUICK_IMG_SIZE / width;
width = MAX_QUICK_IMG_SIZE;
} else {
width *= MAX_QUICK_IMG_SIZE / height;
height = MAX_QUICK_IMG_SIZE;
}
}
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, width, height);
canvas.toBlob(resolve, 'image/jpeg', 100);
});
}