From f52d987515079c8a1cfb78201fa5e1298d85525b Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 4 Dec 2017 15:03:43 +0100 Subject: [PATCH] Ability to resize avatars before uploading them --- bower.json | 3 +- customize.dist/translations/messages.fr.js | 2 + customize.dist/translations/messages.js | 2 + www/common/common-ui-elements.js | 8 ++- www/common/sframe-common-file.js | 4 +- www/profile/app-profile.less | 3 ++ www/profile/inner.js | 57 ++++++++++++++++++++-- 7 files changed, 73 insertions(+), 6 deletions(-) diff --git a/bower.json b/bower.json index 10ab90388..fad124ba9 100644 --- a/bower.json +++ b/bower.json @@ -44,7 +44,8 @@ "open-sans-fontface": "^1.4.2", "bootstrap-tokenfield": "^0.12.1", "localforage": "^1.5.2", - "html2canvas": "^0.4.1" + "html2canvas": "^0.4.1", + "croppie": "^2.5.0" }, "resolutions": { "bootstrap": "v4.0.0-alpha.6" diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index 7a0ee42d4..81b8c9421 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -298,6 +298,8 @@ define(function () { out.profile_namePlaceholder = 'Nom ou pseudo pour le profil'; out.profile_avatar = "Avatar"; out.profile_upload = " Importer un nouvel avatar"; + out.profile_uploadSizeError = "Erreur : votre avatar doit avoir une taille inférieure à {0}"; + out.profile_uploadTypeError = "Erreur : le format de votre avatar est invalide. Les formats autorisés sont : {0}"; out.profile_error = "Erreur lors de la création du profil : {0}"; out.profile_register = "Vous devez vous inscrire pour pouvoir créer un profil !"; out.profile_create = "Créer un profil"; diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index c37420611..160cf72fd 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -301,6 +301,8 @@ define(function () { out.profile_namePlaceholder = 'Name displayed in your profile'; out.profile_avatar = "Avatar"; out.profile_upload = " Upload a new avatar"; + out.profile_uploadSizeError = "Error: your avatar must be smaller than {0}"; + out.profile_uploadTypeError = "Error: your avatar type is not allowed. Allowed types are: {0}"; out.profile_error = "Error while creating your profile: {0}"; out.profile_register = "You have to sign up to create a profile!"; out.profile_create = "Create a profile"; diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 19d4e03bf..c060b0cdc 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -98,7 +98,13 @@ define([ target: data.target }; if (data.filter && !data.filter(file)) { - UI.log('Invalid avatar (type or size)'); + return; + } + if (data.transformer) { + data.transformer(file, function (newFile) { + data.FM.handleFile(newFile, ev); + if (callback) { callback(); } + }); return; } data.FM.handleFile(file, ev); diff --git a/www/common/sframe-common-file.js b/www/common/sframe-common-file.js index a07ce8e0c..4d0370122 100644 --- a/www/common/sframe-common-file.js +++ b/www/common/sframe-common-file.js @@ -212,7 +212,9 @@ define([ queue.next(); }; - var showNamePrompt = true; + // Don't show the rename prompt if we don't want to store the file in the drive (avatar) + var showNamePrompt = !config.noStore; + var promptName = function (file, cb) { var extIdx = file.name.lastIndexOf('.'); var name = extIdx !== -1 ? file.name.slice(0,extIdx) : file.name; diff --git a/www/profile/app-profile.less b/www/profile/app-profile.less index f7cd747d3..21e659a03 100644 --- a/www/profile/app-profile.less +++ b/www/profile/app-profile.less @@ -73,6 +73,9 @@ margin: 5px; } } + .cp-app-profile-resizer { + text-align: center; + } #cp-app-profile-displayname, #cp-app-profile-link { width: 100%; height: 40px; diff --git a/www/profile/inner.js b/www/profile/inner.js index 2728dc15e..88903ac57 100644 --- a/www/profile/inner.js +++ b/www/profile/inner.js @@ -11,6 +11,7 @@ define([ '/customize/messages.js', '/bower_components/marked/marked.min.js', 'cm/lib/codemirror', + '/bower_components/croppie/croppie.min.js', 'cm/mode/markdown/markdown', @@ -20,6 +21,7 @@ define([ 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', 'less!/bower_components/components-font-awesome/css/font-awesome.min.css', 'less!/customize/src/less2/main.less', + 'css!/bower_components/croppie/croppie.css', ], function ( $, Crypto, @@ -32,7 +34,8 @@ define([ Realtime, Messages, Marked, - CodeMirror + CodeMirror, + Croppie ) { var APP = window.APP = { @@ -253,12 +256,44 @@ define([ createEditableInput($block, LINK_ID, placeholder, getValue, setValue); }; + var AVATAR_SIZE_LIMIT = 0.5; var allowedMediaTypes = [ 'image/png', 'image/jpeg', 'image/jpg', 'image/gif', ]; + var transformAvatar = function (file, cb) { + if (file.type === 'image/gif') { return void cb(file); } + var $croppie = $('
', { + 'class': 'cp-app-profile-resizer' + }); + + var todo = function () { + UI.confirm($croppie[0], function (yes) { + if (!yes) { return; } + $croppie.croppie('result', { + type: 'blob', + size: {width: 300, height: 300} + }).then(function(blob) { + blob.lastModifiedDate = new Date(); + blob.name = 'avatar'; + cb(blob); + }); + }); + }; + + var reader = new FileReader(); + reader.onload = function(e) { + $croppie.croppie({ + url: e.target.result, + viewport: { width: 100, height: 100 }, + boundary: { width: 400, height: 300 }, + }); + todo(); + }; + reader.readAsDataURL(file); + }; var addAvatar = function ($container) { var $block = $('
', {id: AVATAR_ID}).appendTo($container); var $span = $('').appendTo($block); @@ -318,14 +353,30 @@ define([ } }; APP.FM = common.createFileManager(fmConfig); + var accepted = ".gif,.jpg,.jpeg,.png"; var data = { FM: APP.FM, filter: function (file) { var sizeMB = Util.bytesToMegabytes(file.size); var type = file.type; - return sizeMB <= 0.5 && allowedMediaTypes.indexOf(type) !== -1; + // We can't resize .gif so we have to display an error if it is too big + if (sizeMB > AVATAR_SIZE_LIMIT && type === 'image/gif') { + UI.log(Messages._getKey('profile_uploadSizeError', [ + Messages._getKey('formattedMB', [AVATAR_SIZE_LIMIT]) + ])); + return false; + } + // Display an error if the image type is not allowed + if (allowedMediaTypes.indexOf(type) === -1) { + UI.log(Messages._getKey('profile_uploadTypeError', [ + accepted.split(',').join(', ') + ])); + return false; + } + return true; }, - accept: ".gif,.jpg,.jpeg,.png" + transformer: transformAvatar, + accept: accepted }; var $upButton = common.createButton('upload', false, data); $upButton.text(Messages.profile_upload);