diff --git a/app/assets/javascripts/discourse/components/avatar-uploader.js.es6 b/app/assets/javascripts/discourse/components/avatar-uploader.js.es6 new file mode 100644 index 000000000..353fb5a4c --- /dev/null +++ b/app/assets/javascripts/discourse/components/avatar-uploader.js.es6 @@ -0,0 +1,30 @@ +import UploadMixin from 'discourse/mixins/upload'; + +export default Em.Component.extend(UploadMixin, { + tagName: 'span', + imageIsNotASquare: false, + type: 'avatar', + + uploadUrl: Discourse.computed.url('username', '/users/%@/preferences/user_image'), + + uploadButtonText: function() { + return this.get("uploading") ? I18n.t("uploading") : I18n.t("user.change_avatar.upload_picture"); + }.property("uploading"), + + uploadDone: function(data) { + var self = this; + + // indicates the users is using an uploaded avatar + this.set("custom_avatar_upload_id", data.result.upload_id); + + // display a warning whenever the image is not a square + this.set("imageIsNotASquare", data.result.width !== data.result.height); + // in order to be as much responsive as possible, we're cheating a bit here + // indeed, the server gives us back the url to the file we've just uploaded + // often, this file is not a square, so we need to crop it properly + // this will also capture the first frame of animated avatars when they're not allowed + Discourse.Utilities.cropAvatar(data.result.url, data.files[0].type).then(function(avatarTemplate) { + self.set("uploadedAvatarTemplate", avatarTemplate); + }); + } +}); diff --git a/app/assets/javascripts/discourse/components/image-uploader.js.es6 b/app/assets/javascripts/discourse/components/image-uploader.js.es6 index 5db2fd235..095bf6cab 100644 --- a/app/assets/javascripts/discourse/components/image-uploader.js.es6 +++ b/app/assets/javascripts/discourse/components/image-uploader.js.es6 @@ -1,6 +1,6 @@ -export default Em.Component.extend({ - uploading: false, - uploadProgress: 0, +import UploadMixin from 'discourse/mixins/upload'; + +export default Em.Component.extend(UploadMixin, { backgroundStyle: function() { var imageUrl = this.get('imageUrl'); @@ -9,50 +9,11 @@ export default Em.Component.extend({ return "background-image: url(" + imageUrl + ")"; }.property('imageUrl'), - _initializeUploader: function() { - var $upload = this.$('input[type=file]'), // note: we can't cache this as fileupload replaces the input after upload - self = this; - - $upload.fileupload({ - url: this.get('uploadUrl'), - dataType: "json", - fileInput: $upload, - formData: { image_type: this.get('type') } - }); - - $upload.on('fileuploadsubmit', function (e, data) { - var result = Discourse.Utilities.validateUploadedFiles(data.files, true); - self.setProperties({ uploadProgress: 0, uploading: result }); - return result; - }); - $upload.on("fileuploadprogressall", function(e, data) { - var progress = parseInt(data.loaded / data.total * 100, 10); - self.set("uploadProgress", progress); - }); - $upload.on("fileuploaddone", function(e, data) { - if(data.result.url) { - self.set('imageUrl', data.result.url); - } else { - bootbox.alert(I18n.t('post.errors.upload')); - } - }); - $upload.on("fileuploadfail", function(e, data) { - Discourse.Utilities.displayErrorForUpload(data); - }); - $upload.on("fileuploadalways", function() { - self.setProperties({ uploading: false, uploadProgress: 0}); - }); - }.on('didInsertElement'), - - _destroyUploader: function() { - this.$('input[type=file]').fileupload('destroy'); - }.on('willDestroyElement'), + uploadDone: function(data) { + this.set('imageUrl', data.result.url); + }, actions: { - selectFile: function() { - this.$('input[type=file]').click(); - }, - trash: function() { this.set('imageUrl', null); this.sendAction('clear'); diff --git a/app/assets/javascripts/discourse/mixins/upload.js.es6 b/app/assets/javascripts/discourse/mixins/upload.js.es6 new file mode 100644 index 000000000..58b864801 --- /dev/null +++ b/app/assets/javascripts/discourse/mixins/upload.js.es6 @@ -0,0 +1,54 @@ +export default Em.Mixin.create({ + uploading: false, + uploadProgress: 0, + + uploadDone: function() { + Em.warn("You should implement `uploadDone`"); + }, + + _initializeUploader: function() { + var $upload = this.$('input[type=file]'), // note: we can't cache this as fileupload replaces the input after upload + self = this; + + $upload.fileupload({ + url: this.get('uploadUrl'), + dataType: "json", + fileInput: $upload, + formData: { image_type: this.get('type') }, + pasteZone: this.$() + }); + + $upload.on('fileuploadsubmit', function (e, data) { + var result = Discourse.Utilities.validateUploadedFiles(data.files, true); + self.setProperties({ uploadProgress: 0, uploading: result }); + return result; + }); + $upload.on("fileuploadprogressall", function(e, data) { + var progress = parseInt(data.loaded / data.total * 100, 10); + self.set("uploadProgress", progress); + }); + $upload.on("fileuploaddone", function(e, data) { + if(data.result.url) { + self.uploadDone(data); + } else { + bootbox.alert(I18n.t('post.errors.upload')); + } + }); + $upload.on("fileuploadfail", function(e, data) { + Discourse.Utilities.displayErrorForUpload(data); + }); + $upload.on("fileuploadalways", function() { + self.setProperties({ uploading: false, uploadProgress: 0}); + }); + }.on('didInsertElement'), + + _destroyUploader: function() { + this.$('input[type=file]').fileupload('destroy'); + }.on('willDestroyElement'), + + actions: { + selectFile: function() { + this.$('input[type=file]').click(); + } + } +}); diff --git a/app/assets/javascripts/discourse/models/user.js b/app/assets/javascripts/discourse/models/user.js index bc01551b7..23c19acdb 100644 --- a/app/assets/javascripts/discourse/models/user.js +++ b/app/assets/javascripts/discourse/models/user.js @@ -350,7 +350,6 @@ Discourse.User = Discourse.Model.extend({ @returns {Promise} the result of the clear profile background request */ clearProfileBackground: function() { - var user = this; return Discourse.ajax("/users/" + this.get("username_lower") + "/preferences/profile_background/clear", { type: 'PUT', data: { } diff --git a/app/assets/javascripts/discourse/templates/components/avatar-uploader.js.handlebars b/app/assets/javascripts/discourse/templates/components/avatar-uploader.js.handlebars new file mode 100644 index 000000000..287071b98 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/avatar-uploader.js.handlebars @@ -0,0 +1,10 @@ + + +{{#if uploading}} + {{i18n upload_selector.uploading}} {{view.uploadProgress}}% +{{/if}} +{{#if imageIsNotASquare}} +