Port image cropper to new popup
This commit is contained in:
parent
974b98ed8e
commit
e0000bade6
|
@ -4873,12 +4873,15 @@
|
|||
</div>
|
||||
</div>
|
||||
<!-- various fullscreen popups -->
|
||||
<template id="popup_template" data-i18n="[popup-button-save]popup-button-save;[popup-button-yes]popup-button-yes;[popup-button-no]popup-button-no;[popup-button-cancel]popup-button-cancel;[popup-button-import]popup-button-import" popup-button-save="Save" popup-button-yes="Yes" popup-button-no="No" popup-button-cancel="Cancel" popup-button-import="Import"> <!-- localization data holder for popups -->
|
||||
<template id="popup_template" data-i18n="[popup-button-save]popup-button-save;[popup-button-yes]popup-button-yes;[popup-button-no]popup-button-no;[popup-button-cancel]popup-button-cancel;[popup-button-import]popup-button-import;[popup-button-crop]popup-button-crop" popup-button-save="Save" popup-button-yes="Yes" popup-button-no="No" popup-button-cancel="Cancel" popup-button-import="Import" popup-button-crop="Crop"> <!-- localization data holder for popups -->
|
||||
<dialog class="popup">
|
||||
<div class="popup-body">
|
||||
<div class="popup-content">
|
||||
<h3 class="popup-header">text</h3>
|
||||
</div>
|
||||
<div class="popup-crop-wrap">
|
||||
<img class="popup-crop-image" src="">
|
||||
</div>
|
||||
<textarea class="popup-input text_pole result-control" rows="1" data-result="1" data-result-event="submit"></textarea>
|
||||
<div class="popup-controls">
|
||||
<div class="popup-button-ok menu_button result-control" data-result="1" data-i18n="Delete">Delete</div>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { power_user } from './power-user.js';
|
||||
import { removeFromArray, runAfterAnimation, uuidv4 } from './utils.js';
|
||||
|
||||
/** @readonly */
|
||||
|
@ -11,6 +12,8 @@ export const POPUP_TYPE = {
|
|||
INPUT: 3,
|
||||
/** Popup without any button controls. Used to simply display content, with a small X in the corner. */
|
||||
DISPLAY: 4,
|
||||
/** Popup that displays an image to crop. Returns a cropped image in result. */
|
||||
CROP: 5,
|
||||
};
|
||||
|
||||
/** @readonly */
|
||||
|
@ -36,6 +39,8 @@ export const POPUP_RESULT = {
|
|||
* @property {CustomPopupButton[]|string[]?} [customButtons=null] - Custom buttons to add to the popup. If only strings are provided, the buttons will be added with default options, and their result will be in order from `2` onward.
|
||||
* @property {(popup: Popup) => boolean?} [onClosing=null] - Handler called before the popup closes, return `false` to cancel the close
|
||||
* @property {(popup: Popup) => void?} [onClose=null] - Handler called after the popup closes, but before the DOM is cleaned up
|
||||
* @property {number?} [cropAspect=null] - Aspect ratio for the crop popup
|
||||
* @property {string?} [cropImage=null] - Image URL to display in the crop popup
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -84,6 +89,8 @@ export class Popup {
|
|||
/** @type {HTMLElement} */ okButton;
|
||||
/** @type {HTMLElement} */ cancelButton;
|
||||
/** @type {HTMLElement} */ closeButton;
|
||||
/** @type {HTMLElement} */ cropWrap;
|
||||
/** @type {HTMLImageElement} */ cropImage;
|
||||
/** @type {POPUP_RESULT|number?} */ defaultResult;
|
||||
/** @type {CustomPopupButton[]|string[]?} */ customButtons;
|
||||
|
||||
|
@ -92,6 +99,7 @@ export class Popup {
|
|||
|
||||
/** @type {POPUP_RESULT|number} */ result;
|
||||
/** @type {any} */ value;
|
||||
/** @type {any} */ cropData;
|
||||
|
||||
/** @type {HTMLElement} */ lastFocus;
|
||||
|
||||
|
@ -106,7 +114,7 @@ export class Popup {
|
|||
* @param {string} [inputValue=''] - The initial value of the input field
|
||||
* @param {PopupOptions} [options={}] - Additional options for the popup
|
||||
*/
|
||||
constructor(content, type, inputValue = '', { okButton = null, cancelButton = null, rows = 1, wide = false, wider = false, large = false, transparent = false, allowHorizontalScrolling = false, allowVerticalScrolling = false, defaultResult = POPUP_RESULT.AFFIRMATIVE, customButtons = null, onClosing = null, onClose = null } = {}) {
|
||||
constructor(content, type, inputValue = '', { okButton = null, cancelButton = null, rows = 1, wide = false, wider = false, large = false, transparent = false, allowHorizontalScrolling = false, allowVerticalScrolling = false, defaultResult = POPUP_RESULT.AFFIRMATIVE, customButtons = null, onClosing = null, onClose = null, cropAspect = null, cropImage = null } = {}) {
|
||||
Popup.util.popups.push(this);
|
||||
|
||||
// Make this popup uniquely identifiable
|
||||
|
@ -128,6 +136,8 @@ export class Popup {
|
|||
this.okButton = this.dlg.querySelector('.popup-button-ok');
|
||||
this.cancelButton = this.dlg.querySelector('.popup-button-cancel');
|
||||
this.closeButton = this.dlg.querySelector('.popup-button-close');
|
||||
this.cropWrap = this.dlg.querySelector('.popup-crop-wrap');
|
||||
this.cropImage = this.dlg.querySelector('.popup-crop-image');
|
||||
|
||||
this.dlg.setAttribute('data-id', this.id);
|
||||
if (wide) this.dlg.classList.add('wide_dialogue_popup');
|
||||
|
@ -169,6 +179,7 @@ export class Popup {
|
|||
// General styling for all types first, that might be overriden for specific types below
|
||||
this.input.style.display = 'none';
|
||||
this.closeButton.style.display = 'none';
|
||||
this.cropWrap.style.display = 'none';
|
||||
|
||||
switch (type) {
|
||||
case POPUP_TYPE.TEXT: {
|
||||
|
@ -190,6 +201,22 @@ export class Popup {
|
|||
this.closeButton.style.display = 'block';
|
||||
break;
|
||||
}
|
||||
case POPUP_TYPE.CROP: {
|
||||
this.cropWrap.style.display = 'block';
|
||||
this.cropImage.src = cropImage;
|
||||
if (!okButton) this.okButton.textContent = template.getAttribute('popup-button-crop');
|
||||
$(this.cropImage).cropper({
|
||||
aspectRatio: cropAspect ?? 2 / 3,
|
||||
autoCropArea: 1,
|
||||
viewMode: 2,
|
||||
rotatable: false,
|
||||
crop: function (event) {
|
||||
this.cropData = event.detail;
|
||||
this.cropData.want_resize = !power_user.never_resize_avatars;
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
console.warn('Unknown popup type.', type);
|
||||
break;
|
||||
|
@ -347,6 +374,13 @@ export class Popup {
|
|||
else value = false; // Might a custom negative value?
|
||||
}
|
||||
|
||||
// Cropped image should be returned as a data URL
|
||||
if (this.type === POPUP_TYPE.CROP) {
|
||||
value = result >= POPUP_RESULT.AFFIRMATIVE
|
||||
? $(this.cropImage).data('cropper').getCroppedCanvas().toDataURL('image/jpeg')
|
||||
: null;
|
||||
}
|
||||
|
||||
this.value = value;
|
||||
this.result = result;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { callPopup, getCropPopup, getRequestHeaders } from '../script.js';
|
||||
import { getRequestHeaders } from '../script.js';
|
||||
import { POPUP_RESULT, POPUP_TYPE, callGenericPopup } from './popup.js';
|
||||
import { renderTemplateAsync } from './templates.js';
|
||||
import { ensureImageFormatSupported, getBase64Async, humanFileSize } from './utils.js';
|
||||
|
@ -727,14 +727,14 @@ async function openUserProfile() {
|
|||
*/
|
||||
async function cropAndUploadAvatar(handle, file) {
|
||||
const dataUrl = await getBase64Async(await ensureImageFormatSupported(file));
|
||||
const croppedImage = await callPopup(getCropPopup(dataUrl), 'avatarToCrop', '', { cropAspect: 1 });
|
||||
const croppedImage = await callGenericPopup('Set the crop position of the avatar image', POPUP_TYPE.CROP, '', { cropAspect: 1, cropImage: dataUrl });
|
||||
if (!croppedImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
await changeAvatar(handle, String(croppedImage));
|
||||
|
||||
return croppedImage;
|
||||
return String(croppedImage);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4154,13 +4154,20 @@ h5 {
|
|||
grid-template-columns: 340px auto;
|
||||
}
|
||||
|
||||
#avatarCropWrap {
|
||||
#avatarCropWrap,
|
||||
.popup-crop-wrap {
|
||||
margin: 10px auto;
|
||||
max-height: 90%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#avatarToCrop {
|
||||
.popup-crop-wrap {
|
||||
max-height: 75vh;
|
||||
max-height: 75svh;
|
||||
}
|
||||
|
||||
#avatarToCrop,
|
||||
.popup-crop-wrap img {
|
||||
max-width: 100%;
|
||||
/* This rule is very important, please do not ignore this! */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue