404 lines
12 KiB
JavaScript
404 lines
12 KiB
JavaScript
class MetaParser {
|
|
static parse() {
|
|
let file;
|
|
const metas = document.querySelectorAll("meta[name]");
|
|
|
|
metas.forEach(meta => {
|
|
const name = meta.getAttribute("name");
|
|
const data = this.metaToObject(meta);
|
|
if (name === "file") {
|
|
file = data;
|
|
}
|
|
});
|
|
return file;
|
|
}
|
|
|
|
static metaToObject(meta) {
|
|
const obj = {};
|
|
for (const attr of meta.attributes) {
|
|
let value = attr.value;
|
|
if (value === "true") {
|
|
value = true;
|
|
} else if (value === "false") {
|
|
value = false;
|
|
} else if (Number.isSafeInteger(value) && !isNaN(value) && value.trim() !== "") {
|
|
value = Number(value);
|
|
}
|
|
obj[attr.name] = value;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
let file = MetaParser.parse(),
|
|
currentScale = 1.0,
|
|
maxScale = 16,
|
|
minScale = 0.5,
|
|
isDragging = false,
|
|
hasMoved = false,
|
|
downX = 0,
|
|
downY = 0,
|
|
startX = 0,
|
|
startY = 0,
|
|
currentX = 0,
|
|
currentY = 0,
|
|
requesting = false;
|
|
|
|
let qualitySelector = document.getElementById("quality-selector");
|
|
qualitySelector.addEventListener("change", switchQuality.bind(this));
|
|
|
|
let convertButton = document.getElementById("convert-button");
|
|
convertButton.addEventListener("click", sendConvertRequest.bind(this));
|
|
|
|
let saveButton = document.getElementById("save-button");
|
|
saveButton.addEventListener("click", convertDraftDone.bind(this));
|
|
|
|
let resetButton = document.getElementById("reset-button");
|
|
resetButton.addEventListener("click", resetImage.bind(this));
|
|
|
|
let preview = document.getElementById("preview");
|
|
preview.style.display = "block";
|
|
|
|
let previewHeader = document.getElementById("preview-header");
|
|
|
|
let previewView = document.getElementById("preview-view");
|
|
previewView.addEventListener("wheel", handleWheel.bind(this));
|
|
previewView.addEventListener("mousedown", startDrag.bind(this));
|
|
|
|
let imageWrapper = document.getElementById("image-wrapper");
|
|
|
|
let previewImg = document.getElementById("preview-img");
|
|
let originalImg = document.getElementById("original-img");
|
|
|
|
originalImg.addEventListener("error", collectRaw.bind(this));
|
|
|
|
let originalSize = document.getElementById("original-size");
|
|
if (originalSize.textContent == "") {
|
|
collectRaw();
|
|
} else {
|
|
originalImg.src = `/files/${file.id_str}.${file.filename.split(".")[1]}`;
|
|
}
|
|
|
|
let denoiseSelector = document.getElementById("denoise-selector");
|
|
denoiseSelector.addEventListener("change", switchDeNoiseLevel.bind(this));
|
|
|
|
let denoiseButton = document.getElementById("denoise-button");
|
|
denoiseButton.addEventListener("click", sendDeNoiseRequest.bind(this));
|
|
|
|
function switchDeNoiseLevel() {
|
|
level = denoiseSelector.value;
|
|
let element = document.getElementById("l" + level);
|
|
if (element.dataset.converted) {
|
|
previewImg.src = `/files/${file.id_str}_l${level}.png`;
|
|
previewImg.style.opacity = 1
|
|
previewHeader.style.backgroundColor = "#333"
|
|
}
|
|
}
|
|
|
|
function sendDeNoiseRequest() {
|
|
if (requesting) {
|
|
alert("Image is converting");
|
|
return;
|
|
}
|
|
|
|
level = denoiseSelector.value;
|
|
|
|
let element = document.getElementById("l" + level);
|
|
if (element.dataset.converted) {
|
|
alert(`Image already denoise with ${level} level`);
|
|
return;
|
|
}
|
|
|
|
requesting = true;
|
|
denoiseButton.textContent = "denoising"
|
|
denoiseButton.style.backgroundColor = "rgb(50, 80, 80)";
|
|
|
|
fetch(`/api/task/files/denoise-draft/${file.id_str}/${level}`)
|
|
.then(response => {
|
|
response.json().then((resjson) => {
|
|
switch (response.status) {
|
|
case 200:
|
|
element.dataset.converted = true;
|
|
element.textContent += ` - ok`;
|
|
previewImg.src = `/files/${file.id_str}_l${level}.png`;
|
|
break;
|
|
default:
|
|
alert(`转换发生错误:${resjson.msg}: ${resjson.error}`);
|
|
}
|
|
});
|
|
})
|
|
.finally(() => {
|
|
denoiseButton.textContent = "denoise"
|
|
denoiseButton.style.backgroundColor = "#444";
|
|
requesting = false;
|
|
})
|
|
.catch(error => {
|
|
alert(`请求失败: ${error}`);
|
|
});
|
|
}
|
|
|
|
function switchQuality() {
|
|
quality = qualitySelector.value;
|
|
let element = document.getElementById("q" + quality);
|
|
if (element.dataset.converted) {
|
|
previewImg.src = `/files/${file.id_str}_q${quality}.webp`;
|
|
previewImg.style.opacity = 1
|
|
previewHeader.style.backgroundColor = "#333"
|
|
}
|
|
}
|
|
|
|
function sendConvertRequest() {
|
|
if (requesting) {
|
|
alert("Image is converting");
|
|
return;
|
|
}
|
|
|
|
quality = qualitySelector.value;
|
|
|
|
let element = document.getElementById("q" + quality);
|
|
if (element.dataset.converted) {
|
|
alert(`Image already converted with ${quality}% quality`);
|
|
return;
|
|
} else if (element.dataset.oversize) {
|
|
alert(`Image is too large to convert with ${quality}% quality`);
|
|
return;
|
|
}
|
|
|
|
requesting = true;
|
|
convertButton.textContent = "converting"
|
|
convertButton.style.backgroundColor = "rgb(50, 80, 80)";
|
|
|
|
fetch(`/api/task/files/convert-draft/webp/${file.id_str}/${quality}`)
|
|
.then(response => {
|
|
response.json().then((resjson) => {
|
|
switch (response.status) {
|
|
case 200:
|
|
element.dataset.converted = true;
|
|
element.textContent += ` - ${resjson.size_str_converted}`;
|
|
previewImg.src = `/files/${file.id_str}_q${quality}.webp`;
|
|
break;
|
|
case 417:
|
|
element.dataset.oversize = true;
|
|
element.textContent += ` - oversize`;
|
|
alert(`Image converted size bigger than original size, cancelled`)
|
|
break;
|
|
default:
|
|
alert(`转换发生错误:${resjson.msg}: ${resjson.error}`);
|
|
}
|
|
});
|
|
})
|
|
.finally(() => {
|
|
convertButton.textContent = "convert"
|
|
convertButton.style.backgroundColor = "#444";
|
|
requesting = false;
|
|
})
|
|
.catch(error => {
|
|
alert(`请求失败: ${error}`);
|
|
});
|
|
}
|
|
|
|
function convertDraftDone() {
|
|
if (requesting) {
|
|
alert("Request is already in progress");
|
|
return;
|
|
}
|
|
|
|
quality = qualitySelector.value;
|
|
|
|
requesting = true;
|
|
saveButton.textContent = "saving"
|
|
saveButton.style.backgroundColor = "rgb(50, 80, 80)";
|
|
|
|
fetch(`/api/task/files/convert-draft-done/webp/${file.id_str}/${quality}`)
|
|
.then(response => {
|
|
response.json().then((resjson) => {
|
|
switch (response.status) {
|
|
case 200:
|
|
break;
|
|
default:
|
|
alert(`发生错误:${resjson.msg}: ${resjson.error}`);
|
|
}
|
|
});
|
|
})
|
|
.finally(() => {
|
|
saveButton.textContent = "saved"
|
|
saveButton.style.backgroundColor = "#444";
|
|
requesting = false;
|
|
})
|
|
.catch(error => {
|
|
alert(`请求失败: ${error}`);
|
|
});
|
|
}
|
|
|
|
function resetImage() {
|
|
if (requesting) {
|
|
alert("another request is already in progress");
|
|
return;
|
|
}
|
|
|
|
requesting = true;
|
|
resetButton.textContent = "resetting"
|
|
resetButton.style.backgroundColor = "rgb(50, 80, 80)";
|
|
fetch(`/api/task/files/convert-reset/${file.id_str}`)
|
|
.then(response => {
|
|
response.json().then((resjson) => {
|
|
switch (response.status) {
|
|
case 200:
|
|
break;
|
|
default:
|
|
alert(`发生错误:${resjson.msg}: ${resjson.error}`);
|
|
}
|
|
});
|
|
})
|
|
.finally(() => {
|
|
resetButton.textContent = "reset"
|
|
resetButton.style.backgroundColor = "#444";
|
|
requesting = false;
|
|
})
|
|
.catch(error => {
|
|
alert(`请求失败: ${error}`);
|
|
});
|
|
}
|
|
|
|
function collectRaw() {
|
|
if (confirm(`The original image could not be loaded. Need try download it to the server?`)) {
|
|
fetch(`/api/task/files/convert-raw/${file.id_str}`)
|
|
.then(response => {
|
|
response.json().then((resjson) => {
|
|
switch (response.status) {
|
|
case 200:
|
|
originalImg.src = resjson.url;
|
|
originalSize.textContent = resjson.size_str;
|
|
break;
|
|
default:
|
|
alert(`发生错误:${resjson.msg}: ${resjson.error}`);
|
|
return
|
|
}
|
|
});
|
|
})
|
|
.catch(error => {
|
|
alert(`请求失败: ${error}`);
|
|
});
|
|
}
|
|
}
|
|
|
|
document.addEventListener('keydown', (e) => {
|
|
if (e.ctrlKey) {
|
|
previewImg.style.opacity = 0
|
|
previewHeader.style.display = "none"
|
|
}
|
|
|
|
switch (e.key) {
|
|
case 'ArrowDown':
|
|
e.preventDefault();
|
|
if (qualitySelector.value <= 35) return;
|
|
qualitySelector.value = String(Number(qualitySelector.value) - 5)
|
|
switchQuality();
|
|
break;
|
|
case 'ArrowUp':
|
|
e.preventDefault();
|
|
if (qualitySelector.value >= 90) return;
|
|
qualitySelector.value = String(Number(qualitySelector.value) + 5)
|
|
switchQuality();
|
|
break;
|
|
}
|
|
});
|
|
|
|
document.addEventListener('keyup', (e) => {
|
|
if (e.key === 'Control') {
|
|
previewImg.style.opacity = 1
|
|
previewHeader.style.display = "flex"
|
|
}
|
|
});
|
|
|
|
function handleWheel(e) {
|
|
e.preventDefault();
|
|
const step =
|
|
currentScale >= 4 ? 0.4 :
|
|
currentScale >= 2 ? 0.2 : 0.1;
|
|
const delta = e.deltaY > 0 ? -step : step;
|
|
const newScale = parseFloat((currentScale + delta).toFixed(10));
|
|
|
|
if (newScale >= minScale && newScale <= maxScale) {
|
|
const ratio = newScale / currentScale;
|
|
const rect = previewView.getBoundingClientRect();
|
|
|
|
const offsetX = e.clientX - (rect.left + rect.width / 2);
|
|
const offsetY = e.clientY - (rect.top + rect.height / 2);
|
|
|
|
currentX = offsetX * (1 - ratio) + currentX * ratio;
|
|
currentY = offsetY * (1 - ratio) + currentY * ratio;
|
|
currentScale = newScale;
|
|
updateImageTransform();
|
|
}
|
|
}
|
|
|
|
function startDrag(e) {
|
|
if (e.button !== 0) return;
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
isDragging = true;
|
|
hasMoved = false;
|
|
startX = e.clientX - currentX;
|
|
startY = e.clientY - currentY;
|
|
downX = e.clientX;
|
|
downY = e.clientY;
|
|
imageWrapper.classList.add("dragging");
|
|
bindDragEvents();
|
|
}
|
|
|
|
function doDrag(e) {
|
|
if (!isDragging) return;
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
const dx = e.clientX - downX;
|
|
const dy = e.clientY - downY;
|
|
if (Math.abs(dx) > 2 || Math.abs(dy) > 2) {
|
|
hasMoved = true;
|
|
}
|
|
currentX = e.clientX - startX;
|
|
currentY = e.clientY - startY;
|
|
updateImageTransform();
|
|
}
|
|
|
|
function endDrag(e) {
|
|
if (!isDragging) return;
|
|
if (e) e.stopPropagation();
|
|
|
|
isDragging = false;
|
|
imageWrapper.classList.remove("dragging");
|
|
unbindDragEvents();
|
|
|
|
if (!hasMoved) {
|
|
previewImg.style.opacity = previewImg.style.opacity === "0" ? "1" : "0";
|
|
previewHeader.style.display = previewImg.style.opacity === "0" ? "none" : "flex";
|
|
}
|
|
}
|
|
|
|
function bindDragEvents() {
|
|
previewView.addEventListener("mousemove", doDrag.bind(this));
|
|
previewView.addEventListener("mouseup", endDrag.bind(this));
|
|
previewView.addEventListener("mouseleave", endDrag.bind(this));
|
|
}
|
|
|
|
function unbindDragEvents() {
|
|
previewView.removeEventListener("mousemove", doDrag.bind(this));
|
|
previewView.removeEventListener("mouseup", endDrag.bind(this));
|
|
previewView.removeEventListener("mouseleave", endDrag.bind(this));
|
|
}
|
|
|
|
function resetTransform() {
|
|
currentScale = 1.0;
|
|
currentX = 0;
|
|
currentY = 0;
|
|
updateImageTransform();
|
|
}
|
|
|
|
function updateImageTransform() {
|
|
imageWrapper.style.transform = `translate(${currentX}px, ${currentY}px) scale(${currentScale})`;
|
|
}
|
|
});
|