diff --git a/keyserver/src/creators/upload-creator.js b/keyserver/src/creators/upload-creator.js --- a/keyserver/src/creators/upload-creator.js +++ b/keyserver/src/creators/upload-creator.js @@ -32,6 +32,7 @@ +dimensions: Dimensions, +loop: boolean, +encryptionKey?: string, + +thumbHash?: string, }; async function createUploads( viewer: Viewer, @@ -45,7 +46,8 @@ const uploadRows = uploadInfos.map(uploadInfo => { const id = ids.shift(); const secret = crypto.randomBytes(8).toString('hex'); - const { content, dimensions, mediaType, loop, encryptionKey } = uploadInfo; + const { content, dimensions, mediaType, loop, encryptionKey, thumbHash } = + uploadInfo; const buffer = content.storage === 'keyserver' ? content.buffer : Buffer.alloc(0); const blobHolder = @@ -69,7 +71,13 @@ buffer, secret, Date.now(), - JSON.stringify({ ...dimensions, loop, blobHolder, encryptionKey }), + JSON.stringify({ + ...dimensions, + loop, + blobHolder, + encryptionKey, + thumbHash, + }), ], }; }); diff --git a/keyserver/src/uploads/media-utils.js b/keyserver/src/uploads/media-utils.js --- a/keyserver/src/uploads/media-utils.js +++ b/keyserver/src/uploads/media-utils.js @@ -49,6 +49,7 @@ +inputLoop: boolean, +inputEncryptionKey: ?string, +inputMimeType: ?string, + +inputThumbHash: ?string, +size: number, // in bytes }; async function validateAndConvert( @@ -61,9 +62,15 @@ inputLoop, inputEncryptionKey, inputMimeType, + inputThumbHash, size, // in bytes } = input; + const passthroughParams = { + loop: inputLoop, + ...(inputThumbHash ? { thumbHash: inputThumbHash } : undefined), + }; + // we don't want to transcode encrypted files if (inputEncryptionKey) { invariant( @@ -81,12 +88,12 @@ } return { + ...passthroughParams, name: initialName, mime: inputMimeType, mediaType, content: { storage: 'keyserver', buffer: initialBuffer }, dimensions: inputDimensions, - loop: inputLoop, encryptionKey: inputEncryptionKey, }; } @@ -106,12 +113,12 @@ 'inputDimensions should be set in validateAndConvert', ); return { + ...passthroughParams, mime: mime, mediaType: mediaType, name: initialName, content: { storage: 'keyserver', buffer: initialBuffer }, dimensions: inputDimensions, - loop: inputLoop, }; } @@ -120,7 +127,7 @@ return null; } - return convertImage( + const convertedImage = await convertImage( initialBuffer, mime, initialName, @@ -128,6 +135,14 @@ inputLoop, size, ); + if (!convertedImage) { + return null; + } + + return { + ...passthroughParams, + ...convertedImage, + }; } async function convertImage( diff --git a/keyserver/src/uploads/uploads.js b/keyserver/src/uploads/uploads.js --- a/keyserver/src/uploads/uploads.js +++ b/keyserver/src/uploads/uploads.js @@ -72,6 +72,11 @@ if (inputMimeType && typeof inputMimeType !== 'string') { throw new ServerError('invalid_parameters'); } + const inputThumbHash = + files.length === 1 && body.thumbHash ? body.thumbHash : null; + if (inputThumbHash && typeof inputThumbHash !== 'string') { + throw new ServerError('invalid_parameters'); + } const validationResults = await Promise.all( files.map(({ buffer, size, originalname }) => @@ -82,6 +87,7 @@ inputLoop, inputEncryptionKey, inputMimeType, + inputThumbHash, size, }), ), @@ -102,6 +108,7 @@ encryptionKey: t.String, mimeType: t.String, loop: t.maybe(t.Boolean), + thumbHash: t.maybe(t.String), }); async function uploadMediaMetadataResponder( @@ -126,6 +133,7 @@ encryptionKey, dimensions: { width, height }, loop: loop ?? false, + thumbHash: request.thumbHash, }; const [result] = await createUploads(viewer, [uploadInfo]); diff --git a/lib/actions/upload-actions.js b/lib/actions/upload-actions.js --- a/lib/actions/upload-actions.js +++ b/lib/actions/upload-actions.js @@ -17,7 +17,8 @@ export type MultimediaUploadExtras = Shape<{ ...Dimensions, loop: boolean, - encryptionKey?: string, + encryptionKey: string, + thumbHash: ?string, }>; const uploadMediaMetadata = @@ -61,6 +62,9 @@ if (extras.encryptionKey) { stringExtras.encryptionKey = extras.encryptionKey; } + if (extras.thumbHash) { + stringExtras.thumbHash = extras.thumbHash; + } // also pass MIME type if available if (multimedia.type && typeof multimedia.type === 'string') { diff --git a/lib/types/media-types.js b/lib/types/media-types.js --- a/lib/types/media-types.js +++ b/lib/types/media-types.js @@ -82,6 +82,7 @@ +encryptionKey: string, +mimeType: string, +loop?: boolean, + +thumbHash?: string, }; export type FFmpegStatistics = {