diff --git a/public/src/client/account/header.js b/public/src/client/account/header.js index c12c25701f..e0cb899ff0 100644 --- a/public/src/client/account/header.js +++ b/public/src/client/account/header.js @@ -94,8 +94,6 @@ define('forum/account/header', [ title: '[[user:upload-cover-picture]]', socketMethod: 'user.updateCover', aspectRatio: NaN, - allowSkippingCrop: true, - restrictImageDimension: false, paramName: 'uid', paramValue: ajaxify.data.theirid, accept: '.png,.jpg,.bmp', diff --git a/public/src/client/groups/details.js b/public/src/client/groups/details.js index 8dde2e3eab..30f20f9739 100644 --- a/public/src/client/groups/details.js +++ b/public/src/client/groups/details.js @@ -50,8 +50,6 @@ define('forum/groups/details', [ title: '[[groups:upload-group-cover]]', socketMethod: 'groups.cover.update', aspectRatio: NaN, - allowSkippingCrop: true, - restrictImageDimension: false, paramName: 'groupName', paramValue: groupName, }, function (imageUrlOnServer) { diff --git a/public/src/modules/accounts/picture.js b/public/src/modules/accounts/picture.js index 6fe37df734..254fc93dd8 100644 --- a/public/src/modules/accounts/picture.js +++ b/public/src/modules/accounts/picture.js @@ -171,11 +171,10 @@ define('accounts/picture', [ pictureCropper.show({ socketMethod: 'user.uploadCroppedPicture', route: config.relative_path + '/api/user/' + ajaxify.data.userslug + '/uploadpicture', - aspectRatio: 1 / 1, + aspectRatio: 1, paramName: 'uid', paramValue: ajaxify.data.theirid, fileSize: ajaxify.data.maximumProfileImageSize, - allowSkippingCrop: false, title: '[[user:upload-picture]]', description: '[[user:upload-a-picture]]', accept: ajaxify.data.allowedProfileImageExtensions, @@ -203,7 +202,6 @@ define('accounts/picture', [ url: url, socketMethod: 'user.uploadCroppedPicture', aspectRatio: 1, - allowSkippingCrop: false, paramName: 'uid', paramValue: ajaxify.data.theirid, }, onUploadComplete); diff --git a/public/src/modules/pictureCropper.js b/public/src/modules/pictureCropper.js index 6b0e9f8b6d..006856a86b 100644 --- a/public/src/modules/pictureCropper.js +++ b/public/src/modules/pictureCropper.js @@ -48,99 +48,71 @@ define('pictureCropper', ['alerts'], function (alerts) { const Cropper = (await import(/* webpackChunkName: "cropperjs" */ 'cropperjs')).default; let cropperTool = new Cropper(img, { - aspectRatio: data.aspectRatio, - autoCropArea: 1, - viewMode: 1, - checkCrossOrigin: true, - cropmove: function () { - if (data.restrictImageDimension) { - if (cropperTool.cropBoxData.width > data.imageDimension) { - cropperTool.setCropBoxData({ - width: data.imageDimension, - }); - } - if (cropperTool.cropBoxData.height > data.imageDimension) { - cropperTool.setCropBoxData({ - height: data.imageDimension, - }); - } + template: ` + + + + + + `, + }); + + const cropperSelection = cropperTool.getCropperSelection(); + const cropperImage = cropperTool.getCropperImage(); + + cropperSelection.aspectRatio = data.aspectRatio; + + cropperImage.$ready(async function () { + if (!await checkCORS(cropperSelection, data)) { + return cropperModal.modal('hide'); + } + + cropperModal.find('.rotate').on('click', function () { + const degrees = this.getAttribute('data-degrees'); + const radians = degrees * Math.PI / 180; + cropperImage.$rotate(radians); + }); + + cropperModal.find('.flip').on('click', function () { + const method = this.getAttribute('data-method'); + if (method === 'scaleX') { + cropperImage.$scale(-1, 1); + } else { + cropperImage.$scale(1, -1); } - }, - ready: function () { - if (!checkCORS(cropperTool, data)) { - return cropperModal.modal('hide'); + }); + + cropperModal.find('.reset').on('click', function () { + cropperImage.$resetTransform(); + cropperSelection.$reset(); + }); + + cropperModal.find('.crop-btn').on('click', async function () { + $(this).addClass('disabled'); + const imageData = await checkCORS(cropperSelection, data); + if (!imageData) { + return; } - if (data.restrictImageDimension) { - const origDimension = (img.width < img.height) ? img.width : img.height; - const dimension = (origDimension > data.imageDimension) ? data.imageDimension : origDimension; - cropperTool.setCropBoxData({ - width: dimension, - height: dimension, - }); - } + cropperModal.find('#upload-progress-bar').css('width', '0%'); + cropperModal.find('#upload-progress-box').show().removeClass('hide'); - cropperModal.find('.rotate').on('click', function () { - const degrees = this.getAttribute('data-degrees'); - cropperTool.rotate(degrees); - }); - - cropperModal.find('.flip').on('click', function () { - const option = this.getAttribute('data-option'); - const method = this.getAttribute('data-method'); - if (method === 'scaleX') { - cropperTool.scaleX(option); - } else { - cropperTool.scaleY(option); - } - this.setAttribute('data-option', option * -1); - }); - - cropperModal.find('.reset').on('click', function () { - cropperTool.reset(); - }); - - cropperModal.find('.crop-btn').on('click', function () { - $(this).addClass('disabled'); - const imageData = checkCORS(cropperTool, data); - if (!imageData) { - return; + socketUpload({ + data: data, + imageData: imageData, + progressBarEl: cropperModal.find('#upload-progress-bar'), + }, function (err, result) { + if (err) { + cropperModal.find('#upload-progress-box').hide(); + cropperModal.find('.upload-btn').removeClass('disabled'); + cropperModal.find('.crop-btn').removeClass('disabled'); + return alerts.error(err); } - cropperModal.find('#upload-progress-bar').css('width', '0%'); - cropperModal.find('#upload-progress-box').show().removeClass('hide'); - - socketUpload({ - data: data, - imageData: imageData, - progressBarEl: cropperModal.find('#upload-progress-bar'), - }, function (err, result) { - if (err) { - cropperModal.find('#upload-progress-box').hide(); - cropperModal.find('.upload-btn').removeClass('disabled'); - cropperModal.find('.crop-btn').removeClass('disabled'); - return alerts.error(err); - } - - callback(result.url); - cropperModal.modal('hide'); - }); + callback(result.url); + cropperModal.modal('hide'); }); - - - cropperModal.find('.upload-btn').on('click', async function () { - $(this).addClass('disabled'); - cropperTool.destroy(); - const Cropper = (await import(/* webpackChunkName: "cropperjs" */ 'cropperjs')).default; - cropperTool = new Cropper(img, { - viewMode: 1, - autoCropArea: 1, - ready: function () { - cropperModal.find('.crop-btn').trigger('click'); - }, - }); - }); - }, + }); }); }); }; @@ -175,12 +147,18 @@ define('pictureCropper', ['alerts'], function (alerts) { doUpload(); } - function checkCORS(cropperTool, data) { + async function checkCORS(selection, data) { let imageData; try { + const canvasOpts = { + beforeDraw: function (context) { + context.imageSmoothingQuality = 'high'; + }, + }; + const canvas = await selection.$toCanvas(canvasOpts); imageData = data.imageType ? - cropperTool.getCroppedCanvas().toDataURL(data.imageType) : - cropperTool.getCroppedCanvas().toDataURL(); + canvas.toDataURL(data.imageType) : + canvas.toDataURL(); } catch (err) { const corsErrors = [ 'The operation is insecure.', @@ -232,8 +210,6 @@ define('pictureCropper', ['alerts'], function (alerts) { imageType: file.type, socketMethod: data.socketMethod, aspectRatio: data.aspectRatio, - allowSkippingCrop: data.allowSkippingCrop, - restrictImageDimension: data.restrictImageDimension, imageDimension: data.imageDimension, paramName: data.paramName, paramValue: data.paramValue, diff --git a/src/meta/css.js b/src/meta/css.js index 4b7e999383..ab0c17f7d8 100644 --- a/src/meta/css.js +++ b/src/meta/css.js @@ -29,7 +29,6 @@ const buildImports = { '@import "@adactive/bootstrap-tagsinput/src/bootstrap-tagsinput";', source, '@import "jquery-ui";', - '@import "cropperjs/dist/cropper";', ].join('\n'); }, admin: function (source) { diff --git a/src/views/modals/crop_picture.tpl b/src/views/modals/crop_picture.tpl index 519bacd5ec..7920dd13fc 100644 --- a/src/views/modals/crop_picture.tpl +++ b/src/views/modals/crop_picture.tpl @@ -1,16 +1,15 @@ -