Adds support for importing, filtering, and exporting images in batches.
// ==UserScript==
// @name HEISEI VHS Batch Filtering
// @namespace https://greasyfork.org/en/users/1582013
// @version 1.0
// @description Adds support for importing, filtering, and exporting images in batches.
// @author FreekyCreep
// @license GNU GPLv3
// @match https://hiyameshi-retro-pack.web.app/apps/Heisei-VHS/
// ==/UserScript==
// jshint esversion: 8
(function () {
//site elements
const PROCESSING_OVERLAY = document.getElementById("processing-overlay");
const FILE_UPLOAD = document.getElementById("file-upload");
const BTN_EXPORT = document.getElementById("btn-export");
//custom toolbar button
const customInputButton = document.getElementById("btn-upload-trigger").cloneNode(true);
customInputButton.id += "-freeky";
customInputButton.removeAttribute("data-tooltip");
customInputButton.style.cssText = "background:#4ab0d9; color:white;";
//custom multi input
const customInput = document.getElementById("file-upload").cloneNode();
customInput.id += "-freeky";
customInput.multiple = true;
//cancel button
let pendingCancel = false;
const cancelButton = document.createElement("button");
cancelButton.style.cssText = "cursor:pointer; position:fixed; top:12px; left:12px; padding:12px; background:#ff6b6b; color:white; border: 2px dashed black; border-radius:8px; z-index:9999; visibility:hidden;";
//functions
async function customInputHandler(e) {
pendingCancel = false;
cancelButton.style.visibility = "visible";
const files = Array.from(e.target.files);
for (let i = 0; i < files.length; i++) {
if (pendingCancel) break;
cancelButton.textContent = `Cancel batch... (${i}/${files.length})`;
const dataTransfer = new DataTransfer();
dataTransfer.items.add(files[i]);
FILE_UPLOAD.files = dataTransfer.files;
FILE_UPLOAD.dispatchEvent(new Event("change"));
do {
await sleep(100);
} while (!PROCESSING_OVERLAY.classList.contains("is-hidden"));
BTN_EXPORT.click();
}
cancelButton.style.visibility = "hidden";
if (!pendingCancel) alert("Batch complete!");
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
//events
customInput.addEventListener("change", customInputHandler);
customInputButton.addEventListener("click", () => customInput.click());
cancelButton.addEventListener("click", () => { pendingCancel = true; });
//DOM
BTN_EXPORT.after(customInputButton);
customInputButton.after(customInput);
document.querySelector("main").appendChild(cancelButton);
})();