From 6c1c8be79433f87bef9d768da7b8fa4ec9bb18d7 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 22 May 2014 17:37:02 +1000 Subject: [PATCH] Work in progress, keeping avatars locally This introduces a new model to store the avatars and 3 uploads per user (gravatar, system and custom) user can then pick which they want. --- .../controllers/avatar-selector.js.es6 | 18 +- .../discourse/helpers/application_helpers.js | 26 +- .../javascripts/discourse/models/user.js | 9 + .../discourse/models/user_action.js | 2 +- .../discourse/routes/preferences_routes.js | 7 +- .../modal/avatar_selector.js.handlebars | 14 +- .../views/modal/avatar_selector_view.js | 2 +- app/assets/stylesheets/desktop/modal.scss | 8 + app/controllers/avatar_controller.rb | 46 +++ app/controllers/users_controller.rb | 2 - app/jobs/regular/create_missing_avatars.rb | 10 + app/jobs/regular/generate_avatars.rb | 67 ---- app/jobs/scheduled/detect_avatars.rb | 31 -- app/models/user.rb | 37 ++- app/models/user_action.rb | 4 +- app/models/user_avatar.rb | 53 +++ app/models/user_stat.rb | 1 - app/serializers/basic_post_serializer.rb | 5 + app/serializers/basic_user_serializer.rb | 21 +- app/serializers/post_serializer.rb | 3 +- .../topic_post_count_serializer.rb | 10 +- app/serializers/user_action_serializer.rb | 20 +- app/serializers/user_serializer.rb | 25 +- config/initializers/06-mini_profiler.rb | 1 + config/locales/client.en.yml | 4 +- config/locales/server.en.yml | 1 + config/routes.rb | 2 + config/site_settings.yml | 7 +- db/fixtures/005_users.rb | 5 + ...emove_has_custom_avatar_from_user_stats.rb | 5 + db/migrate/20140522003151_add_user_avatars.rb | 12 + lib/avatar_detector.rb | 32 -- lib/avatar_lookup.rb | 2 - lib/composer_messages_finder.rb | 2 +- lib/letter_avatar.rb | 303 ++++++++++++++++++ lib/tasks/avatars.rake | 12 - spec/components/avatar_detector_spec.rb | 67 ---- .../composer_messages_finder_spec.rb | 2 +- spec/controllers/users_controller_spec.rb | 2 - spec/models/user_avatar_spec.rb | 21 ++ spec/models/user_spec.rb | 37 +-- spec/spec_helper.rb | 7 + 42 files changed, 626 insertions(+), 319 deletions(-) create mode 100644 app/controllers/avatar_controller.rb create mode 100644 app/jobs/regular/create_missing_avatars.rb delete mode 100644 app/jobs/regular/generate_avatars.rb delete mode 100644 app/jobs/scheduled/detect_avatars.rb create mode 100644 app/models/user_avatar.rb create mode 100644 db/migrate/20140520063859_remove_has_custom_avatar_from_user_stats.rb create mode 100644 db/migrate/20140522003151_add_user_avatars.rb delete mode 100644 lib/avatar_detector.rb create mode 100644 lib/letter_avatar.rb delete mode 100644 lib/tasks/avatars.rake delete mode 100644 spec/components/avatar_detector_spec.rb create mode 100644 spec/models/user_avatar_spec.rb diff --git a/app/assets/javascripts/discourse/controllers/avatar-selector.js.es6 b/app/assets/javascripts/discourse/controllers/avatar-selector.js.es6 index ed165e45c..af6642bc7 100644 --- a/app/assets/javascripts/discourse/controllers/avatar-selector.js.es6 +++ b/app/assets/javascripts/discourse/controllers/avatar-selector.js.es6 @@ -10,12 +10,14 @@ export default Discourse.Controller.extend(Discourse.ModalFunctionality, { actions: { - useUploadedAvatar: function() { this.set("use_uploaded_avatar", true); }, - useGravatar: function() { this.set("use_uploaded_avatar", false); } - }, - - avatarTemplate: function() { - return this.get("use_uploaded_avatar") ? this.get("uploaded_avatar_template") : this.get("gravatar_template"); - }.property("use_uploaded_avatar", "uploaded_avatar_template", "gravatar_template") - + useUploadedAvatar: function() { + this.set("selected", "uploaded"); + }, + useGravatar: function() { + this.set("selected", "gravatar"); + }, + useSystem: function() { + this.set("selected", "system"); + } + } }); diff --git a/app/assets/javascripts/discourse/helpers/application_helpers.js b/app/assets/javascripts/discourse/helpers/application_helpers.js index 269f1c8da..6b3bacaf7 100644 --- a/app/assets/javascripts/discourse/helpers/application_helpers.js +++ b/app/assets/javascripts/discourse/helpers/application_helpers.js @@ -183,16 +183,6 @@ Handlebars.registerHelper('avatar', function(user, options) { var username = Em.get(user, 'username'); if (!username) username = Em.get(user, options.hash.usernamePath); - var avatarTemplate; - var template = options.hash.template; - if (template && template !== 'avatar_template') { - avatarTemplate = Em.get(user, template); - if (!avatarTemplate) avatarTemplate = Em.get(user, 'user.' + template); - } - - if (!avatarTemplate) avatarTemplate = Em.get(user, 'avatar_template'); - if (!avatarTemplate) avatarTemplate = Em.get(user, 'user.avatar_template'); - var title; if (!options.hash.ignoreTitle) { // first try to get a title @@ -209,6 +199,10 @@ Handlebars.registerHelper('avatar', function(user, options) { } } + // this is simply done to ensure we cache images correctly + var uploadedAvatarId = Em.get(user, 'uploaded_avatar_id') || Em.get(user, 'user.uploaded_avatar_id') || "_1"; + var avatarTemplate = Discourse.User.avatarTemplate(username,uploadedAvatarId); + return new Handlebars.SafeString(Discourse.Utilities.avatarImg({ size: options.hash.imageSize, extraClasses: Em.get(user, 'extras') || options.hash.extraClasses, @@ -228,11 +222,19 @@ Handlebars.registerHelper('avatar', function(user, options) { @for Handlebars **/ Ember.Handlebars.registerBoundHelper('boundAvatar', function(user, options) { + + var username = Em.get(user, 'username'); + + console.log(options.hash); + + var uploadId = (options.hash.uploadId && Em.get(user, options.hash.uploadId)) || Em.get(user, 'uploaded_avatar_id'); + var avatarTemplate = Discourse.User.avatarTemplate(username,uploadId); + return new Handlebars.SafeString(Discourse.Utilities.avatarImg({ size: options.hash.imageSize, - avatarTemplate: Em.get(user, options.hash.template || 'avatar_template') + avatarTemplate: avatarTemplate })); -}, 'avatar_template', 'uploaded_avatar_template', 'gravatar_template'); +}, 'uploadId', 'username', 'uploaded_avatar_id'); /** Nicely format a date without binding or returning HTML diff --git a/app/assets/javascripts/discourse/models/user.js b/app/assets/javascripts/discourse/models/user.js index 96ad0dd66..5e1138cc1 100644 --- a/app/assets/javascripts/discourse/models/user.js +++ b/app/assets/javascripts/discourse/models/user.js @@ -326,6 +326,10 @@ Discourse.User = Discourse.Model.extend({ }); }, + avatarTemplate: function(){ + return Discourse.User.avatarTemplate(this.get('username'),this.get('uploaded_avatar_id')); + }.property('uploaded_avatar_id', 'username'), + /* Change avatar selection @@ -413,6 +417,11 @@ Discourse.User = Discourse.Model.extend({ }); Discourse.User.reopenClass(Discourse.Singleton, { + + avatarTemplate: function(username, uploadedAvatarId){ + return Discourse.getURL("/avatar/" + username.toLowerCase() + "/{size}/" + uploadedAvatarId + ".png"); + }, + /** Find a `Discourse.User` for a given username. diff --git a/app/assets/javascripts/discourse/models/user_action.js b/app/assets/javascripts/discourse/models/user_action.js index d4c32108b..9af722d11 100644 --- a/app/assets/javascripts/discourse/models/user_action.js +++ b/app/assets/javascripts/discourse/models/user_action.js @@ -184,7 +184,7 @@ Discourse.UserAction = Discourse.Model.extend({ switchToActing: function() { this.setProperties({ username: this.get('acting_username'), - avatar_template: this.get('acting_avatar_template'), + uploaded_avatar_id: this.get('acting_uploaded_avatar_id'), name: this.get('actingDisplayName') }); } diff --git a/app/assets/javascripts/discourse/routes/preferences_routes.js b/app/assets/javascripts/discourse/routes/preferences_routes.js index 1c0f93786..5108dbd87 100644 --- a/app/assets/javascripts/discourse/routes/preferences_routes.js +++ b/app/assets/javascripts/discourse/routes/preferences_routes.js @@ -22,8 +22,11 @@ Discourse.PreferencesRoute = Discourse.RestrictedUserRoute.extend({ // all the properties needed for displaying the avatar selector modal this.controllerFor('avatar-selector').setProperties(this.modelFor('user').getProperties( 'username', 'email', - 'has_uploaded_avatar', 'use_uploaded_avatar', - 'gravatar_template', 'uploaded_avatar_template')); + 'system_avatar_upload_id', + 'gravatr_avatar_upload_id', + 'custom_avatar_upload_id' + ) + ); }, saveAvatarSelection: function() { diff --git a/app/assets/javascripts/discourse/templates/modal/avatar_selector.js.handlebars b/app/assets/javascripts/discourse/templates/modal/avatar_selector.js.handlebars index 1b7e54cc4..a70d12d48 100644 --- a/app/assets/javascripts/discourse/templates/modal/avatar_selector.js.handlebars +++ b/app/assets/javascripts/discourse/templates/modal/avatar_selector.js.handlebars @@ -1,15 +1,19 @@