Files
FileJet/src/main/resources/HTML/script.js

267 lines
10 KiB
JavaScript
Vendored

document.addEventListener('DOMContentLoaded', () => {
const fileList = document.getElementById('file-list');
const backBtn = document.getElementById('back-btn');
const forwardBtn = document.getElementById('forward-btn');
const upBtn = document.getElementById('up-btn');
const addressInput = document.getElementById('address-input');
const searchInput = document.getElementById('search-input');
const statusText = document.getElementById('status-text');
let history = ['/'];
let historyIndex = 0;
let forwardStack = [];
let selectedIndex = -1;
let currentItems = [];
function getCurrentPath() {
return history[historyIndex];
}
function setAddressBar() {
let p = getCurrentPath();
addressInput.value = p === '/' ? 'Computer' : p;
}
function updateSelection() {
const items = fileList.querySelectorAll('.file-item');
items.forEach((item, index) => {
item.classList.toggle('focused', index === selectedIndex);
});
}
function selectItem(index) {
const items = fileList.querySelectorAll('.file-item');
if (index >= 0 && index < items.length) {
selectedIndex = index;
updateSelection();
// Scroll into view
items[selectedIndex].scrollIntoView({ block: 'nearest' });
// Update status
if (currentItems[selectedIndex]) {
const item = currentItems[selectedIndex];
statusText.textContent = `Selected: ${item.name} (${item.isDir ? 'Folder' : 'File'})`;
}
}
}
function openSelectedItem() {
if (selectedIndex >= 0 && selectedIndex < currentItems.length) {
const item = currentItems[selectedIndex];
if (item.isDir) {
let cur = getCurrentPath();
let next = cur.endsWith('/') ? cur + item.name : cur + '/' + item.name;
history = history.slice(0, historyIndex + 1);
history.push(next);
historyIndex++;
forwardStack = [];
selectedIndex = -1;
fetchFiles();
} else {
// Download file
let cur = getCurrentPath();
let filePath = cur.endsWith('/') ? cur + item.name : cur + '/' + item.name;
window.location.href = `/api/download?path=${encodeURIComponent(filePath)}`;
}
}
}
function fetchFiles(searchTerm = '') {
setAddressBar();
statusText.textContent = 'Loading...';
let path = getCurrentPath();
let url = `/api/list-isos?path=${encodeURIComponent(path)}`;
if (searchTerm) {
url += `&search=${encodeURIComponent(searchTerm)}`;
}
fetch(url)
.then(res => {
if (!res.ok) throw new Error('Failed to fetch file list');
return res.json();
})
.then(items => {
fileList.innerHTML = '';
currentItems = [];
selectedIndex = -1;
if (!items.length) {
fileList.innerHTML = '<div class="file-item" style="grid-column: 1 / -1; text-align: center; color: #888;">No files or folders found.</div>';
statusText.textContent = 'No items found';
return;
}
currentItems = items;
items.forEach((item, index) => {
const div = document.createElement('div');
div.className = 'file-item';
div.dataset.index = index;
// Icon
const icon = document.createElement('img');
icon.className = 'icon';
icon.src = item.isDir ? 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTIgM0MxLjQ0NzcyIDMgMSAzLjQ0NzcyIDEgNFYxMkMxIDEyLjU1MjMgMS40NDc3MiAxMyAyIDEzSDE0QzE0LjU1MjMgMTMgMTUgMTIuNTUyMyAxNSAxMlY2QzE1IDUuNDQ3NzIgMTQuNTUyMyA1IDE0IDVIOEw2IDNIMloiIGZpbGw9IiNGRkQ3MDAiLz4KPC9zdmc+' : 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMgM0MyLjQ0NzcyIDMgMiAzLjQ0NzcyIDIgNFYxMkMyIDEyLjU1MjMgMi40NDc3MiAxMyAzIDEzSDEzQzEzLjU1MjMgMTMgMTQgMTIuNTUyMyAxNCAxMlY0QzE0IDMuNDQ3NzIgMTMuNTUyMyAzIDEzIDNIM1oiIGZpbGw9IiM4ODg4ODgiLz4KPC9zdmc+';
icon.onerror = () => icon.style.display = 'none';
div.appendChild(icon);
// Name (show relative path if searching)
const nameSpan = document.createElement('span');
nameSpan.className = 'file-name';
if (searchTerm && item.path) {
nameSpan.textContent = item.path;
} else {
nameSpan.textContent = item.name;
}
div.appendChild(nameSpan);
// Type
const typeSpan = document.createElement('span');
typeSpan.className = 'file-type';
typeSpan.textContent = item.isDir ? 'Folder' : 'File';
div.appendChild(typeSpan);
// Size
const sizeSpan = document.createElement('span');
sizeSpan.className = 'file-size';
sizeSpan.textContent = item.isDir ? '' : '-';
div.appendChild(sizeSpan);
// Date Modified
const dateSpan = document.createElement('span');
dateSpan.className = 'file-date';
dateSpan.textContent = '';
div.appendChild(dateSpan);
// Action
const actionDiv = document.createElement('div');
if (!item.isDir) {
const dlBtn = document.createElement('button');
dlBtn.className = 'download-btn';
dlBtn.textContent = 'Download';
dlBtn.onclick = (e) => {
e.stopPropagation();
let cur = getCurrentPath();
let filePath = cur.endsWith('/') ? cur + item.name : cur + '/' + item.name;
window.location.href = `/api/download?path=${encodeURIComponent(filePath)}`;
};
actionDiv.appendChild(dlBtn);
}
div.appendChild(actionDiv);
// Click handlers
div.onclick = () => {
selectItem(index);
if (item.isDir) {
setTimeout(() => openSelectedItem(), 200);
}
};
fileList.appendChild(div);
});
statusText.textContent = `${items.length} item${items.length !== 1 ? 's' : ''}`;
// Update button states
backBtn.disabled = historyIndex <= 0;
forwardBtn.disabled = historyIndex >= history.length - 1;
upBtn.disabled = getCurrentPath() === '/';
})
.catch(err => {
fileList.innerHTML = `<div class="file-item" style="grid-column: 1 / -1; text-align: center; color: #d9534f;">${err.message}</div>`;
statusText.textContent = 'Error loading files';
});
}
// Navigation event handlers
backBtn.addEventListener('click', () => {
if (historyIndex > 0) {
historyIndex--;
selectedIndex = -1;
fetchFiles();
}
});
forwardBtn.addEventListener('click', () => {
if (historyIndex < history.length - 1) {
historyIndex++;
selectedIndex = -1;
fetchFiles();
}
});
upBtn.addEventListener('click', () => {
let cur = getCurrentPath();
if (cur === '/' || cur === '') return;
let parts = cur.split('/').filter(Boolean);
parts.pop();
let upPath = '/' + parts.join('/');
if (upPath === '') upPath = '/';
history = history.slice(0, historyIndex + 1);
history.push(upPath);
historyIndex++;
selectedIndex = -1;
fetchFiles();
});
addressInput.addEventListener('click', () => {
addressInput.select();
});
searchInput.addEventListener('input', (e) => {
selectedIndex = -1;
fetchFiles(e.target.value);
});
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.target.tagName === 'INPUT') return;
switch(e.key) {
case 'ArrowUp':
e.preventDefault();
if (selectedIndex > 0) {
selectItem(selectedIndex - 1);
} else if (currentItems.length > 0) {
selectItem(currentItems.length - 1);
}
break;
case 'ArrowDown':
e.preventDefault();
if (selectedIndex < currentItems.length - 1) {
selectItem(selectedIndex + 1);
} else if (currentItems.length > 0) {
selectItem(0);
}
break;
case 'Enter':
e.preventDefault();
openSelectedItem();
break;
case 'Escape':
e.preventDefault();
selectedIndex = -1;
updateSelection();
statusText.textContent = `${currentItems.length} item${currentItems.length !== 1 ? 's' : ''}`;
break;
case 'Backspace':
e.preventDefault();
upBtn.click();
break;
case 'F5':
e.preventDefault();
selectedIndex = -1;
fetchFiles(searchInput.value);
break;
case '/':
e.preventDefault();
searchInput.focus();
break;
}
});
// Initial load
fetchFiles();
});