337 lines
11 KiB
JavaScript
337 lines
11 KiB
JavaScript
|
//import * as avif from '@jsquash/avif'; // TBD
|
||
|
//import * as webp from '@jsquash/webp'; // TBD
|
||
|
import * as jpeg from '@jsquash/jpeg';
|
||
|
import * as png from '@jsquash/png';
|
||
|
import optimise from '@jsquash/oxipng/optimise';
|
||
|
const { __ } = wp.i18n; // Import __() from wp.i18n
|
||
|
|
||
|
(function () {
|
||
|
|
||
|
const bulkBtn = document.querySelector("input[name='squeeze_bulk']")
|
||
|
const bulkLogInput = document.querySelector("[name='squeeze_bulk_log']")
|
||
|
const squeeze_bulk_ids = document.querySelector("input[name='squeeze_bulk_ids']")?.value ?? null;
|
||
|
const uncompressedIDs = squeeze_bulk_ids ? squeeze_bulk_ids.split(",") : [];
|
||
|
|
||
|
async function decode(sourceType, fileBuffer) {
|
||
|
switch (sourceType) {
|
||
|
//case 'avif':
|
||
|
// return await avif.decode(fileBuffer);
|
||
|
case 'jpeg':
|
||
|
return await jpeg.decode(fileBuffer);
|
||
|
case 'png':
|
||
|
return await png.decode(fileBuffer);
|
||
|
//case 'webp':
|
||
|
// return await webp.decode(fileBuffer);
|
||
|
default:
|
||
|
throw new Error(`Unknown source type: ${sourceType}`);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function encode(outputType, imageData) {
|
||
|
const options = JSON.parse(squeeze.options);
|
||
|
|
||
|
switch (outputType) {
|
||
|
//case 'avif':
|
||
|
// return await avif.encode(imageData);
|
||
|
case 'jpeg':
|
||
|
const jpegOptions = {}
|
||
|
for (const [key, value] of Object.entries(options)) {
|
||
|
if (key.includes('jpeg')) {
|
||
|
const keyName = key.replace('jpeg_', '')
|
||
|
jpegOptions[keyName] = value
|
||
|
}
|
||
|
}
|
||
|
return await jpeg.encode(imageData, jpegOptions);
|
||
|
case 'png':
|
||
|
const pngOptions = {}
|
||
|
for (const [key, value] of Object.entries(options)) {
|
||
|
if (key.includes('png')) {
|
||
|
const keyName = key.replace('png_', '')
|
||
|
pngOptions[keyName] = value
|
||
|
}
|
||
|
}
|
||
|
return await png.encode(imageData, pngOptions);
|
||
|
//case 'webp':
|
||
|
// return await webp.encode(imageData);
|
||
|
default:
|
||
|
throw new Error(`Unknown output type: ${outputType}`);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function convert(sourceType, outputType, fileBuffer) {
|
||
|
const imageData = await decode(sourceType, fileBuffer);
|
||
|
return encode(outputType, imageData);
|
||
|
}
|
||
|
|
||
|
function blobToBase64(blob) {
|
||
|
return new Promise((resolve, _) => {
|
||
|
const reader = new FileReader();
|
||
|
reader.onloadend = () => resolve(reader.result);
|
||
|
reader.readAsDataURL(blob);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
async function showOutput(imageBuffer, outputType) {
|
||
|
const imageBlob = new Blob([imageBuffer], { type: `image/${outputType}` });
|
||
|
const base64String = await blobToBase64(imageBlob);
|
||
|
|
||
|
return base64String;
|
||
|
}
|
||
|
|
||
|
async function handleUpload(attachment, isBulk = false, isSingle = false, target = null) {
|
||
|
const attachmentData = attachment.attributes;
|
||
|
const url = attachmentData?.originalImageURL ?? attachmentData.url;
|
||
|
const mime = attachmentData.mime;
|
||
|
const name = attachmentData.name;
|
||
|
const filename = attachmentData?.originalImageName ?? attachmentData.filename;
|
||
|
const attachmentID = attachmentData.id;
|
||
|
const format = mime.split("/")[1];
|
||
|
const sourceType = format;
|
||
|
const outputType = format;
|
||
|
const options = JSON.parse(squeeze.options);
|
||
|
|
||
|
let imageBuffer;
|
||
|
let fileBuffer;
|
||
|
let base64;
|
||
|
|
||
|
if (format === "png") {
|
||
|
const pngOptions = {}
|
||
|
for (const [key, value] of Object.entries(options)) {
|
||
|
if (key.includes('png')) {
|
||
|
const keyName = key.replace('png_', '')
|
||
|
pngOptions[keyName] = value
|
||
|
}
|
||
|
}
|
||
|
imageBuffer = await fetch(url).then(res => res.arrayBuffer()).then(pngImageBuffer => optimise(pngImageBuffer, pngOptions));
|
||
|
base64 = await showOutput(imageBuffer, outputType);
|
||
|
} else {
|
||
|
let response = await fetch(url);
|
||
|
let blob = await response.blob();
|
||
|
let metadata = {
|
||
|
type: mime
|
||
|
};
|
||
|
let imageObj = new File([blob], name, metadata);
|
||
|
fileBuffer = await imageObj.arrayBuffer();
|
||
|
|
||
|
/*
|
||
|
if (window.Worker) {
|
||
|
//const myWorker = new Worker(new URL(`${squeeze.pluginUrl}/assets/js/worker.js`), { type: "module" });
|
||
|
const myWorker = new Worker(/* webpackChunkName: "foo-worker" */ /*new URL(`./worker.js`, import.meta.url));
|
||
|
myWorker.postMessage(
|
||
|
{
|
||
|
fileBuffer: fileBuffer,
|
||
|
sourceType: sourceType,
|
||
|
outputType: outputType,
|
||
|
}
|
||
|
);
|
||
|
console.log('Message posted to worker');
|
||
|
|
||
|
myWorker.onmessage = function(e) {
|
||
|
console.log('Message received from worker', e.data);
|
||
|
myWorker.terminate();
|
||
|
}
|
||
|
} else {
|
||
|
console.log('Your browser doesn\'t support web workers.');
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
imageBuffer = await convert(sourceType, outputType, fileBuffer);
|
||
|
base64 = await showOutput(imageBuffer, outputType);
|
||
|
}
|
||
|
|
||
|
let data = {
|
||
|
action: 'squeeze_update_attachment',
|
||
|
_ajax_nonce: squeeze.nonce,
|
||
|
filename: filename,
|
||
|
type: 'image',
|
||
|
format: format,
|
||
|
base64: base64,
|
||
|
attachmentID: attachmentID,
|
||
|
url: url,
|
||
|
}
|
||
|
|
||
|
jQuery.ajax({
|
||
|
url: squeeze.ajaxUrl,
|
||
|
type: 'POST',
|
||
|
data: data,
|
||
|
beforeSend: function () {
|
||
|
console.log('data', data)
|
||
|
if (isBulk)
|
||
|
bulkLogInput.value += `#${attachmentID}: ` + __('Compressed successfully, updating...', 'squeeze') + `\r\n`;
|
||
|
},
|
||
|
error: function (error) {
|
||
|
console.error(error)
|
||
|
if (target) {
|
||
|
target.closest("td").querySelector(".squeeze_status").innerText = __('An error has occured. Check the console for details.', 'squeeze')
|
||
|
target.remove();
|
||
|
}
|
||
|
},
|
||
|
success: function (response) {
|
||
|
console.log(response)
|
||
|
if (isBulk) {
|
||
|
if (response.success) {
|
||
|
bulkLogInput.value += `#${attachmentID}: ` + __('Updated successfully', 'squeeze') + `\r\n===============================\r\n`;
|
||
|
handleBulkUpload()
|
||
|
} else {
|
||
|
bulkLogInput.value += `#${attachmentID}: ${response.data}\r\n===============================\r\n`;
|
||
|
}
|
||
|
}
|
||
|
if (isSingle && target) {
|
||
|
target.closest("td").querySelector(".squeeze_status").innerText = response.data;
|
||
|
target.remove();
|
||
|
}
|
||
|
if (!isSingle && !isBulk) {
|
||
|
attachment.set('uploading', false) // resume uploading process
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
}
|
||
|
|
||
|
const handleBulkUpload = () => {
|
||
|
const data = {
|
||
|
action: 'squeeze_get_attachment',
|
||
|
_ajax_nonce: squeeze.nonce,
|
||
|
attachmentID: uncompressedIDs[0],
|
||
|
}
|
||
|
|
||
|
if (uncompressedIDs.length === 0) {
|
||
|
alert(__('All images have been compressed!', 'squeeze'))
|
||
|
bulkBtn.remove();
|
||
|
location.reload();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bulkLogInput.value += `attachment #${uncompressedIDs[0]}: start compressing...\r\n`;
|
||
|
|
||
|
jQuery.ajax({
|
||
|
url: squeeze.ajaxUrl,
|
||
|
type: 'POST',
|
||
|
data: data,
|
||
|
error: function (error) {
|
||
|
console.error(error)
|
||
|
},
|
||
|
success: function (response) {
|
||
|
//console.log(response)
|
||
|
if (response.success) {
|
||
|
const responseData = response.data;
|
||
|
const attachment = {
|
||
|
attributes: {
|
||
|
url: responseData.url,
|
||
|
mime: responseData.mime,
|
||
|
name: responseData.name,
|
||
|
filename: responseData.filename,
|
||
|
id: responseData.id,
|
||
|
}
|
||
|
}
|
||
|
//console.log(attachment, 'attachment')
|
||
|
uncompressedIDs.shift();
|
||
|
handleUpload(attachment, true)
|
||
|
} else {
|
||
|
console.error(response.data)
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function handleRestore(attachmentID, target) {
|
||
|
let data = {
|
||
|
action: 'squeeze_restore_attachment',
|
||
|
_ajax_nonce: squeeze.nonce,
|
||
|
attachmentID: attachmentID,
|
||
|
}
|
||
|
|
||
|
jQuery.ajax({
|
||
|
url: squeeze.ajaxUrl,
|
||
|
type: 'POST',
|
||
|
data: data,
|
||
|
beforeSend: function () {
|
||
|
target.disabled = true;
|
||
|
target.innerText = __('Restore in process...', 'squeeze')
|
||
|
},
|
||
|
error: function (error) {
|
||
|
console.error(error)
|
||
|
target.closest("td").querySelector(".squeeze_status").innerText = __('An error has occured. Check the console for details.', 'squeeze')
|
||
|
target.remove();
|
||
|
},
|
||
|
success: function (response) {
|
||
|
//console.log(response)
|
||
|
target.closest("td").querySelector(".squeeze_status").innerText = response.data; //__('Restored successfully', 'squeeze')
|
||
|
target.remove();
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Handle single compress button click
|
||
|
const handleSingleBtnClick = (event) => {
|
||
|
const attachmentID = event.target.dataset.attachment;
|
||
|
|
||
|
wp?.media?.attachment(attachmentID).fetch().then(function (data) {
|
||
|
const attachment = {
|
||
|
attributes: data
|
||
|
}
|
||
|
handleUpload(attachment, false, true, event.target)
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Handle restore button click
|
||
|
const handleRestoreBtnClick = (event) => {
|
||
|
const attachmentID = event.target.dataset.attachment;
|
||
|
handleRestore(attachmentID, event.target)
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handle single buttons click
|
||
|
*/
|
||
|
function handleSingleButtonsClick() {
|
||
|
document.addEventListener("click", (e) => {
|
||
|
//console.log(e.target, 'e.target')
|
||
|
const singleBtnName = 'squeeze_compress_single';
|
||
|
const restoreBtnName = 'squeeze_restore';
|
||
|
if (e.target.getAttribute("name") === singleBtnName) {
|
||
|
e.target.disabled = true;
|
||
|
e.target.innerText = __('Compressing...', 'squeeze')
|
||
|
handleSingleBtnClick(e)
|
||
|
}
|
||
|
if (e.target.getAttribute("name") === restoreBtnName) {
|
||
|
e.target.disabled = true;
|
||
|
handleRestoreBtnClick(e)
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
handleSingleButtonsClick()
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Handle bulk button click
|
||
|
*/
|
||
|
bulkBtn?.addEventListener("click", (event) => {
|
||
|
if (uncompressedIDs.length === 0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bulkBtn.disabled = true;
|
||
|
handleBulkUpload()
|
||
|
|
||
|
})
|
||
|
|
||
|
// https://wordpress.stackexchange.com/a/131295/186146 - override wp.Uploader.prototype.success
|
||
|
jQuery.extend(wp?.Uploader?.prototype, {
|
||
|
success: function (attachment) {
|
||
|
//console.log(attachment, 'success');
|
||
|
const options = JSON.parse(squeeze.options);
|
||
|
const isAutoCompress = options.auto_compress;
|
||
|
let isImage = attachment.attributes.type === 'image' &&
|
||
|
(attachment.attributes.subtype === 'jpeg' || attachment.attributes.subtype === 'png')
|
||
|
|
||
|
if (isImage && isAutoCompress) {
|
||
|
// set 'uploading' param to true, to pause the uploading process
|
||
|
attachment.set('uploading', true)
|
||
|
handleUpload(attachment)
|
||
|
}
|
||
|
},
|
||
|
});
|
||
|
})();
|
||
|
|
||
|
//console.log(JSON.parse(squeeze.options), 'squeeze.options')
|