diff --git a/js/modules/types/attachment.js b/js/modules/types/attachment.js index b168bd2f9f..80dc12a4c8 100644 --- a/js/modules/types/attachment.js +++ b/js/modules/types/attachment.js @@ -2,6 +2,13 @@ const dataURLToBlob = require('blueimp-canvas-to-blob'); const MIME = require('./mime'); +const { autoOrientImage } = require('../auto_orient_image'); + +// Increment this everytime we change how attachments are processed. This allows us to +// retroactively update existing attachments. As we add more processing steps, we could +// design a pipeline that does this incrementally, e.g. from version 0 (unknown) -> 1, +// 1 --> 2, etc., similar to how we do database migrations: +const CURRENT_PROCESS_VERSION = 1; // // Fields // { @@ -36,14 +43,39 @@ const blobToArrayBuffer = blob => const arrayBufferToBlob = (arrayBuffer, mimeType) => new Blob([arrayBuffer], { type: mimeType }); -// Processing steps: -const withLastNormalizedDate = attachment => Object.assign( - {}, - attachment, - {lastNormalized: new Date().toISOString()}, -); +// Middleware +// type ProcessingStep = Attachment -> Promise Attachment -const autoOrientJPEGs = async (attachment) => { +// ProcessingStep -> ProcessVersion -> ProcessingStep +const setProcessVersion = (next, processVersion) => async (attachment) => { + const isAlreadyProcessed = attachment.processVersion >= processVersion; + if (isAlreadyProcessed) { + return attachment; + } + + let processedAttachment; + try { + processedAttachment = await next(attachment); + } catch (error) { + console.error('Attachment.setProcessVersion: error:', error); + processedAttachment = null; + } + + const hasSuccessfullyProcessed = processedAttachment !== null; + if (!hasSuccessfullyProcessed) { + return attachment; + } + + // TODO: Enable `...` object spread operator syntax: + return Object.assign( + {}, + processedAttachment, + { processVersion } + ); +}; + +// Processing steps +const autoOrientJPEG = async (attachment) => { if (!MIME.isJPEG(attachment.contentType)) { return attachment; } @@ -54,7 +86,6 @@ const autoOrientJPEGs = async (attachment) => { const newAttachment = Object.assign({}, attachment, { data: newDataArrayBuffer, size: newDataArrayBuffer.byteLength, - lastNormalized: new Date().toISOString(), }); // `digest` is no longer valid for auto-oriented image data, so we discard it: @@ -64,8 +95,5 @@ const autoOrientJPEGs = async (attachment) => { }; // Public API - -// Attachment -> Promise -exports.normalize = async attachment => - withLastNormalizedDate(await autoOrientJPEGs(attachment)); - +// ProcessingStep +exports.process = setProcessVersion(autoOrientJPEG, CURRENT_PROCESS_VERSION);