From 075f1b5df4ce5df11848c5100f0e12719dbdba27 Mon Sep 17 00:00:00 2001 From: "Sam X. Chen" Date: Mon, 15 Jul 2019 10:25:16 -0400 Subject: Add Feature: allow to shrink attached/pasted image if server has correponding settings --- client/components/cards/attachments.js | 125 +++++++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 12 deletions(-) (limited to 'client/components/cards/attachments.js') diff --git a/client/components/cards/attachments.js b/client/components/cards/attachments.js index 6b3e38a5..f536a655 100644 --- a/client/components/cards/attachments.js +++ b/client/components/cards/attachments.js @@ -54,7 +54,7 @@ Template.previewAttachedImagePopup.events({ Template.cardAttachmentsPopup.events({ 'change .js-attach-file'(event) { const card = this; - FS.Utility.eachFile(event, f => { + const processFile = f => { const file = new FS.File(f); if (card.isLinkedCard()) { file.boardId = Cards.findOne(card.linkedId).boardId; @@ -66,7 +66,6 @@ Template.cardAttachmentsPopup.events({ file.cardId = card._id; } file.userId = Meteor.userId(); - const attachment = Attachments.insert(file); if (attachment && attachment._id && attachment.isImage()) { @@ -74,6 +73,42 @@ Template.cardAttachmentsPopup.events({ } Popup.close(); + }; + + FS.Utility.eachFile(event, f => { + if ( + MAX_IMAGE_PIXEL > 0 && + typeof f.type === 'string' && + f.type.match(/^image/) + ) { + // is image + const reader = new FileReader(); + reader.onload = function(e) { + const dataurl = e && e.target && e.target.result; + if (dataurl !== undefined) { + shrinkImage({ + dataurl, + maxSize: MAX_IMAGE_PIXEL, + ratio: COMPRESS_RATIO, + toBlob: true, + callback(blob) { + if (blob === false) { + processFile(f); + } else { + blob.name = f.name; + processFile(blob); + } + }, + }); + } else { + // couldn't process it let other function handle it? + processFile(f); + } + }; + reader.readAsDataURL(f); + } else { + processFile(f); + } }); }, 'click .js-computer-upload'(event, templateInstance) { @@ -83,30 +118,96 @@ Template.cardAttachmentsPopup.events({ 'click .js-upload-clipboard-image': Popup.open('previewClipboardImage'), }); +const MAX_IMAGE_PIXEL = Meteor.settings.public.MAX_IMAGE_PIXEL; +const COMPRESS_RATIO = Meteor.settings.public.IMAGE_COMPRESS_RATIO; let pastedResults = null; +const shrinkImage = function(options) { + // shrink image to certain size + const dataurl = options.dataurl, + callback = options.callback, + toBlob = options.toBlob; + let canvas = document.createElement('canvas'), + image = document.createElement('img'); + const maxSize = options.maxSize || 1024; + const ratio = options.ratio || 1.0; + const next = function(result) { + image = null; + canvas = null; + if (typeof callback === 'function') { + callback(result); + } + }; + image.onload = function() { + let width = this.width, + height = this.height; + let changed = false; + if (width > height) { + if (width > maxSize) { + height *= maxSize / width; + width = maxSize; + changed = true; + } + } else if (height > maxSize) { + width *= maxSize / height; + height = maxSize; + changed = true; + } + canvas.width = width; + canvas.height = height; + canvas.getContext('2d').drawImage(this, 0, 0, width, height); + if (changed === true) { + const type = 'image/jpeg'; + if (toBlob) { + canvas.toBlob(next, type, ratio); + } else { + next(canvas.toDataURL(type, ratio)); + } + } else { + next(changed); + } + }; + image.onerror = function() { + next(false); + }; + image.src = dataurl; +}; Template.previewClipboardImagePopup.onRendered(() => { // we can paste image from clipboard - $(document.body).pasteImageReader(results => { + const handle = results => { if (results.dataURL.startsWith('data:image/')) { - $('img.preview-clipboard-image').attr('src', results.dataURL); - pastedResults = results; + const direct = results => { + $('img.preview-clipboard-image').attr('src', results.dataURL); + pastedResults = results; + }; + if (MAX_IMAGE_PIXEL) { + // if has size limitation on image we shrink it before uploading + shrinkImage({ + dataurl: results.dataURL, + maxSize: MAX_IMAGE_PIXEL, + ratio: COMPRESS_RATIO, + callback(changed) { + if (changed !== false && !!changed) { + results.dataURL = changed; + } + direct(results); + }, + }); + } } - }); + }; + + $(document.body).pasteImageReader(handle); // we can also drag & drop image file to it - $(document.body).dropImageReader(results => { - if (results.dataURL.startsWith('data:image/')) { - $('img.preview-clipboard-image').attr('src', results.dataURL); - pastedResults = results; - } - }); + $(document.body).dropImageReader(handle); }); Template.previewClipboardImagePopup.events({ 'click .js-upload-pasted-image'() { const results = pastedResults; if (results && results.file) { + window.oPasted = pastedResults; const card = this; const file = new FS.File(results.file); if (!results.name) { -- cgit v1.2.3-1-g7c22