const imageExtensions = ['gif','jpg','jpeg','png', 'webp'];
const videoExtensions =['mpg', 'mp2', 'mpeg', 'mpe', 'mpv', 'mp4'];
const audioExtensions =['mp3', 'ogg', 'wav', 'flac'];
const mappings = new Map(JSON.parse(localStorage.getItem('mappings')) || []);
let statusLine = document.getElementById('status');
// store for when done with sorting TODO display
let splash = document.getElementById('current-file').innerHTML;
let history = [];
//
// SERVER COMMUNICATION
//
/**
* Only show the server response text if its a 500 internal
*/
function showServerError(fname, status, text) {
if (status == 500) {
message = `in ${fname}: server returned ${status}: '${text}'`;
} else {
message = `in ${fname}: server returned ${status}`;
}
statusLine.textContent = message;
console.error(message);
}
/**
* get the path in which the images are located and can be loaded from, by appending to them to the stagingPath
*/
let stagingPath = "";
async function setStagingPath() {
const response = await fetch("imgsort.php?action=getStagingPath");
if (response.ok) {
stagingPath = await response.text();
}
else {
showServerError("setStagingPath", response.status, text);
}
}
/**
* list of files to be processed
*/
let fileList = [];
async function setFileList() {
const response = await fetch("imgsort.php?action=getFileList");
const text = await response.text();
// console.log(text);
if (response.ok) {
fileList = JSON.parse(text);
// fileList.sort();
}
else {
}
}
//
// RENDERING
//
/*
* Create button for each mapping
*/
function renderMoveButtons() {
const buttons = document.getElementById('move-buttons');
buttons.innerHTML = '';
mappings.forEach((directory, key) => {
const removeButton = document.createElement('button');
removeButton.innerHTML = `${key} ${directory}`;
removeButton.onclick = function() {
moveFile(directory);
};
removeButton.class = "move-button";
buttons.appendChild(removeButton);
});
}
function renderFileList() {
const fileListDiv = document.getElementById('file-list');
fileListDiv.innerHTML = '';
fileList.forEach(file => {
const p = document.createElement('p');
classes = "file-list-item path";
if (file === currentFile) {
classes += " selected-file-list-item";
}
p.setAttribute("class", classes)
p.innerHTML = file;
fileListDiv.appendChild(p);
});
}
let currentFile = "";
let currentFileIdx = null;
function createMediaFileElement(file, autoplay=false) {
const fileExt = file.split('.').pop();
if (imageExtensions.includes(fileExt)) { // if image
let img = document.createElement("img");
img.setAttribute('src', stagingPath + file)
return img;
} else if (videoExtensions.includes(fileExt)) { // if video
let vid = document.createElement("video");
if (autoplay) vid.setAttribute('autoplay', true);
vid.setAttribute('controls', true);
src = document.createElement("source");
src.setAttribute("src", stagingPath + file);
src.setAttribute("type", `video/${fileExt}`);
vid.appendChild(src);
return vid;
} else if (audioExtensions.includes(fileExt)) { // if audio
let aud = document.createElement("audio");
if (autoplay) aud.setAttribute('autoplay', true);
aud.setAttribute('controls', true);
src = document.createElement("source");
src.setAttribute("src", stagingPath + file);
src.setAttribute("type", `audio/${fileExt}`);
aud.appendChild(src);
return aud;
} else { // if none of the above
let p = document.createElement("p");
p.innerHTML = 'No preview available';
return p;
}
}
function renderCurrentFile() {
// const currentFileNameDiv = document.getElementById('current-file-name');
// if (!currentFile) {
// currentFileNameDiv.innerHTML = "No files in staging";
// }
// else {
// currentFileNameDiv.innerHTML = currentFile;
// }
const currentFileDiv = document.getElementById('current-file');
currentFileDiv.innerHTML = "";
if (currentFile) {
let element = createMediaFileElement(currentFile, true);
currentFileDiv.appendChild(element);
} else {
currentFileDiv.innerHTML = splash;
}
}
// load media tag of the next file in hidden div, without autoplay
function preloadNextFile() {
const nextFile = fileList[currentFileIdx+1];
if (!nextFile) {
return
}
const preloadFileDiv = document.getElementById('preload-file');
preloadFileDiv.innerHTML = "";
let element = createMediaFileElement(nextFile, false);
preloadFileDiv.appendChild(element);
console.log("Preloaded " + nextFile);
}
//
// LOGIC
//
// set the currentFile variable according to currentFileIdx
function setCurrentFile() {
// check configuration
if (mappings.size == 0) {
statusLine.textContent = "No mappings configured - Click 'Configure' first";
return;
}
// if none set and there are files
if (currentFileIdx == null && fileList.length > 0) {
currentFileIdx = 0;
}
// else if (currentFileIdx < fileList.length) {
// }
else if (currentFileIdx >= fileList.length) {
currentFileIdx = fileList.length - 1;
}
// if index is valid
if (typeof(currentFileIdx) == 'number' && currentFileIdx >= 0 && currentFileIdx < fileList.length) {
currentFile = fileList[currentFileIdx];
}
else {
currentFileIdx = null;
currentFile = "";
statusLine.textContent = "No more files to sort";
}
renderCurrentFile();
renderFileList();
}
async function moveFile(directory) {
if (!currentFile) {
statusLine.innerHTML = "No file to process!";
return
}
const response = await fetch(`imgsort.php?action=moveFile&file=${escape(currentFile)}&dest=${directory}`);
const text = await response.text();
// console.log(text);
if (response.ok) {
statusLine.textContent = `Moved '${currentFile}' to '${directory}'`;
history.push([currentFile, directory]);
// remove file from list
fileList.splice(currentFileIdx, 1);
// set next file
setCurrentFile();
preloadNextFile();
}
else {
showServerError("moveFile", response.status, text);
}
}
async function undo() {
if (!history.length > 0) {
statusLine.textContent = "Nothing to undo"
return;
}
const [file, directory] = history.pop();
const response = await fetch(`imgsort.php?action=undoFile&file=${escape(file)}&dest=${directory}`);
const text = await response.text();
// console.log(text);
if (response.ok) {
statusLine.innerHTML = `Undo: move '${file}' to '${directory}'`;
await setFileList()
setCurrentFile();
}
else {
showServerError("undo", response.status, text);
}
}
function skip() {
currentFileIdx++;
setCurrentFile();
}
async function initialize() {
await setStagingPath();
await setFileList();
renderMoveButtons();
renderFileList();
// setCurrentFile();
preloadNextFile();
statusLine.textContent = "Loaded";
}
// load existing mappings on page load
window.onload = function() {
initialize();
};
// handle keyboard
document.onkeypress = function(e) {
e = e || window.event;
let keydebug = document.getElementById("keydebug");
if (keydebug) {
keydebug.innerHTML = e.key;
}
if (e.key == "u") {
undo();
}
else if (e.key == "s") {
skip();
}
else if (mappings.has(e.key)) {
moveFile(mappings.get(e.key));
}
}