diff --git a/app/assets/javascripts/application/avatar.js b/app/assets/javascripts/application/avatar.js index 3f4b127bf..c6034c88c 100644 --- a/app/assets/javascripts/application/avatar.js +++ b/app/assets/javascripts/application/avatar.js @@ -38,14 +38,14 @@ $(function () { // on submit take the parameters of the box to crop the avatar $('#form_photo').on("submit", () => { - let total_width = parseInt(getComputedStyle(document.getElementById("containerCrop")).width); - let photo_width = parseInt(getComputedStyle(document.getElementById("foto")).width); + let total_width = parseInt(getComputedStyle(document.getElementById("container_crop")).width); + let photo_width = parseInt(getComputedStyle(document.getElementById("original_img")).width); let left_displacement = total_width - photo_width; $('#height_offset').val(parseInt(panel.css('top')) - 15); $('#width_offset').val(parseInt(panel.css('left')) - 15 - (left_displacement/2)); $('#height_width').val(parseInt(panel.css('width'))); - $('#original_width').val($('#foto').width()); + $('#original_width').val($('#original_img').width()); }); function resize(e) { @@ -93,7 +93,7 @@ $(function () { } function preview_image_modal() { - var preview = document.querySelector('#foto'); + var preview = document.querySelector('#original_img'); var file = document.querySelector('#avatar-js').files[0]; var reader = new FileReader(); diff --git a/app/assets/stylesheets/application/avatar.scss b/app/assets/stylesheets/application/avatar.scss index d87ab1d6b..7ed2d7c8d 100644 --- a/app/assets/stylesheets/application/avatar.scss +++ b/app/assets/stylesheets/application/avatar.scss @@ -6,8 +6,8 @@ #crop_panel { position: absolute; - width: 140px; - height: 140px; + width: 200px; + height: 200px; border-left: 4px dashed black; cursor: move; touch-action: none; @@ -21,7 +21,7 @@ right: 0; width: 16px; height: 100%; - cursor: w-resize; + cursor: ew-resize; } #crop_panel::after { @@ -32,5 +32,5 @@ bottom: 0; width: 100%; height: 16px; - cursor: n-resize; + cursor: ns-resize; } diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index eded58ee7..79e48b807 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -66,14 +66,12 @@ def update end def update_avatar - avatar = params[:avatar] + operation = AvatarGenerator.new(current_user, params) - if avatar && content_type_permitted(avatar.content_type) - current_user.avatar.purge if current_user.avatar.attached? - - crop_image_and_save(current_user, avatar) + if operation.errors.empty? + operation.call else - flash[:error] = t 'users.show.invalid_format' + flash[:error] = operation.errors.join("
") end redirect_to current_user @@ -130,28 +128,4 @@ def redirect_to_after_create name: @user.username) end end - - def crop_image_and_save(user, avatar) - orig_width = params[:original_width].to_i - width = params[:height_width].to_i - left = params[:width_offset].to_i - top = params[:height_offset].to_i - - image_processed = ImageProcessing::MiniMagick. - source(avatar.tempfile). - resize_to_fit(orig_width, nil). - crop("#{width}x#{width}+#{left}+#{top}!"). - convert("png"). - call - - user.avatar.attach( - io: image_processed, - filename: user.username, - content_type: avatar.content_type - ) - end - - def content_type_permitted(avatar_content_type) - %w[image/jpeg image/pjpeg image/png image/x-png].include? avatar_content_type - end end diff --git a/app/services/avatar_generator.rb b/app/services/avatar_generator.rb new file mode 100644 index 000000000..d04187f4c --- /dev/null +++ b/app/services/avatar_generator.rb @@ -0,0 +1,51 @@ +class AvatarGenerator + MAX_SIZE = 5 + CONTENT_TYPES = %w[image/jpeg image/pjpeg image/png image/x-png] + + attr_accessor :errors + + def initialize(user, params) + @user = user + @params = params + @avatar = params[:avatar] + @errors = [] + + validate_avatar + end + + def call + @user.avatar.purge if @user.avatar.attached? + + @user.avatar.attach( + io: process_image, + filename: @user.username, + content_type: @avatar.content_type + ) + end + + private + + def process_image + orig_width = @params[:original_width].to_i + width = @params[:height_width].to_i + left = @params[:width_offset].to_i + top = @params[:height_offset].to_i + + ImageProcessing::MiniMagick. + source(@avatar.tempfile). + resize_to_fit(orig_width, nil). + crop("#{width}x#{width}+#{left}+#{top}!"). + convert("png"). + call + end + + def validate_avatar + if CONTENT_TYPES.exclude?(@avatar.content_type) + @errors << I18n.t("users.show.invalid_format") + end + + if @avatar.size.to_f > MAX_SIZE.megabytes + @errors << I18n.t("users.avatar.max_size_warning", size: MAX_SIZE) + end + end +end diff --git a/app/views/layouts/_messages.html.erb b/app/views/layouts/_messages.html.erb index 0222a2c35..d1db057d0 100644 --- a/app/views/layouts/_messages.html.erb +++ b/app/views/layouts/_messages.html.erb @@ -5,7 +5,7 @@ diff --git a/app/views/users/_avatar.html.erb b/app/views/users/_avatar.html.erb index bd792a6be..df80232cf 100644 --- a/app/views/users/_avatar.html.erb +++ b/app/views/users/_avatar.html.erb @@ -16,25 +16,24 @@