From 8c4e071c00168d07f93496b119db681fbf8dcc78 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 3 Mar 2021 17:20:32 +1100 Subject: [PATCH] crop avatars to what iOS expects --- js/background.js | 7 ++++--- ts/receiver/openGroups.ts | 19 ++++++++++++++++++- ts/util/attachmentsUtil.ts | 30 +++++++++++++++++++++++++----- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/js/background.js b/js/background.js index 3cd2fb634..4f95237f0 100644 --- a/js/background.js +++ b/js/background.js @@ -465,9 +465,10 @@ file: new Blob([data.data], { type: avatar.contentType, }), - maxMeasurements: { - maxSize: 1000 * 1024, // 1Mb for our profile picture - }, + }, + { + maxSide: 640, + maxSize: 1000 * 1024, } ); const dataResized = await window.Signal.Types.Attachment.arrayBufferFromFile( diff --git a/ts/receiver/openGroups.ts b/ts/receiver/openGroups.ts index 694162ef9..dd7014c8e 100644 --- a/ts/receiver/openGroups.ts +++ b/ts/receiver/openGroups.ts @@ -23,10 +23,27 @@ export async function updateOpenGroup( fileReader.readAsArrayBuffer(attachment.file); }); const avatarAttachment: any = await readFile({ file: avatar }); + + // We want a square for iOS + const withBlob = await window.Signal.Util.AttachmentUtil.autoScale( + { + contentType: avatar.type, + file: new Blob([avatarAttachment.data], { + type: avatar.contentType, + }), + }, + { + maxSide: 640, + maxSize: 1000 * 1024, + } + ); + const dataResized = await window.Signal.Types.Attachment.arrayBufferFromFile( + withBlob.file + ); // const tempUrl = window.URL.createObjectURL(avatar); // Get file onto public chat server - const fileObj = await API.serverAPI.putAttachment(avatarAttachment.data); + const fileObj = await API.serverAPI.putAttachment(dataResized); if (fileObj === null) { // problem window.log.warn('File upload failed'); diff --git a/ts/util/attachmentsUtil.ts b/ts/util/attachmentsUtil.ts index 46998f4a3..cb5740654 100644 --- a/ts/util/attachmentsUtil.ts +++ b/ts/util/attachmentsUtil.ts @@ -6,8 +6,15 @@ export interface MaxScaleSize { maxSize?: number; maxHeight?: number; maxWidth?: number; + maxSide?: number; // use this to make avatars cropped if too big and centered if too small. } +/** + * Scale down an image to fit in the required dimension. + * Note: This method won't crop if needed, + * @param attachment The attachment to scale down + * @param maxMeasurements any of those will be used if set + */ export async function autoScale( attachment: T, maxMeasurements?: MaxScaleSize @@ -22,19 +29,31 @@ export async function autoScale( const url = URL.createObjectURL(file); const img = document.createElement('img'); img.onerror = reject; + // tslint:disable-next-line: cyclomatic-complexity img.onload = () => { URL.revokeObjectURL(url); + if ( + maxMeasurements?.maxSide && + (maxMeasurements?.maxHeight || maxMeasurements?.maxWidth) + ) { + reject('Cannot have maxSide and another dimension set together'); + } + const maxSize = maxMeasurements?.maxSize || Constants.CONVERSATION.MAX_ATTACHMENT_FILESIZE_BYTES; - const maxHeight = maxMeasurements?.maxHeight || 4096; - const maxWidth = maxMeasurements?.maxWidth || 4096; + const makeSquare = Boolean(maxMeasurements?.maxSide); + const maxHeight = + maxMeasurements?.maxHeight || maxMeasurements?.maxSide || 4096; + const maxWidth = + maxMeasurements?.maxWidth || maxMeasurements?.maxSide || 4096; if ( img.naturalWidth <= maxWidth && img.naturalHeight <= maxHeight && - file.size <= maxSize + file.size <= maxSize && + !makeSquare ) { resolve(attachment); return; @@ -55,8 +74,9 @@ export async function autoScale( const canvas = (loadImage as any).scale(img, { canvas: true, - maxWidth, - maxHeight, + maxWidth: makeSquare ? maxMeasurements?.maxSide : maxWidth, + maxHeight: makeSquare ? maxMeasurements?.maxSide : maxHeight, + crop: makeSquare, }); let quality = 0.95; let i = 4;