183 lines
6.4 KiB
JavaScript
183 lines
6.4 KiB
JavaScript
// Helper function: decode each segment then re-encode to avoid double encoding.
|
|
function encodeSubpath(subpath) {
|
|
if (!subpath) return '';
|
|
return subpath
|
|
.split('/')
|
|
.map(segment => encodeURIComponent(decodeURIComponent(segment)))
|
|
.join('/');
|
|
}
|
|
|
|
// Global variable for gallery images (updated from current folder)
|
|
let currentGalleryImages = [];
|
|
|
|
// Render breadcrumbs, directories (grid view when appropriate), and files.
|
|
function renderContent(data) {
|
|
let breadcrumbHTML = '';
|
|
data.breadcrumbs.forEach((crumb, index) => {
|
|
breadcrumbHTML += `<a href="#" class="breadcrumb-link" data-path="${crumb.path}">${crumb.name}</a>`;
|
|
if (index < data.breadcrumbs.length - 1) {
|
|
breadcrumbHTML += `<span>></span>`;
|
|
}
|
|
});
|
|
document.getElementById('breadcrumbs').innerHTML = breadcrumbHTML;
|
|
|
|
let contentHTML = '';
|
|
|
|
// Render directories.
|
|
if (data.directories.length > 0) {
|
|
contentHTML += '<ul>';
|
|
// Check if every directory name is short (≤15 characters)
|
|
const areAllShort = data.directories.every(dir => dir.name.length <= 15);
|
|
if (areAllShort) {
|
|
contentHTML += '<div class="directories-grid">';
|
|
data.directories.forEach(dir => {
|
|
contentHTML += `<div class="directory-item">📁 <a href="#" class="directory-link" data-path="${dir.path}">${dir.name}</a></div>`;
|
|
});
|
|
contentHTML += '</div>';
|
|
} else {
|
|
contentHTML += '<ul>';
|
|
data.directories.forEach(dir => {
|
|
contentHTML += `<li class="directory-item">📁 <a href="#" class="directory-link" data-path="${dir.path}">${dir.name}</a></li>`;
|
|
});
|
|
contentHTML += '</ul>';
|
|
}
|
|
}
|
|
|
|
// Render files.
|
|
if (data.files.length > 0) {
|
|
contentHTML += '<ul>';
|
|
data.files.forEach(file => {
|
|
let symbol = '';
|
|
if (file.file_type === 'music') {
|
|
symbol = '🎵';
|
|
} else if (file.file_type === 'image') {
|
|
symbol = '🖼️';
|
|
}
|
|
contentHTML += `<li class="file-item">
|
|
<a href="#" class="play-file" data-url="${file.path}" data-file-type="${file.file_type}">${symbol} ${file.name}</a>`;
|
|
if (file.has_transcript) {
|
|
contentHTML += `<a href="#" class="show-transcript" data-url="${file.transcript_url}" title="Show Transcript">📄</a>`;
|
|
}
|
|
contentHTML += `</li>`;
|
|
});
|
|
contentHTML += '</ul>';
|
|
}
|
|
|
|
document.getElementById('content').innerHTML = contentHTML;
|
|
|
|
// Update global variable for gallery images (only image files).
|
|
currentGalleryImages = data.files
|
|
.filter(f => f.file_type === 'image')
|
|
.map(f => f.path);
|
|
|
|
attachEventListeners(); // Reattach event listeners for newly rendered elements.
|
|
}
|
|
|
|
// Fetch directory data from the API.
|
|
function loadDirectory(subpath) {
|
|
const encodedPath = encodeSubpath(subpath);
|
|
const apiUrl = '/api/path/' + encodedPath;
|
|
fetch(apiUrl)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
renderContent(data);
|
|
})
|
|
.catch(error => {
|
|
console.error('Error loading directory:', error);
|
|
document.getElementById('content').innerHTML = '<p>Error loading directory.</p>';
|
|
});
|
|
}
|
|
|
|
// Attach event listeners for directory, breadcrumb, file, and transcript links.
|
|
function attachEventListeners() {
|
|
// Directory link clicks.
|
|
document.querySelectorAll('.directory-link').forEach(link => {
|
|
link.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
const newPath = this.getAttribute('data-path');
|
|
loadDirectory(newPath);
|
|
history.pushState({ subpath: newPath }, '', newPath ? '/path/' + newPath : '/');
|
|
});
|
|
});
|
|
|
|
// Breadcrumb link clicks.
|
|
document.querySelectorAll('.breadcrumb-link').forEach(link => {
|
|
link.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
const newPath = this.getAttribute('data-path');
|
|
loadDirectory(newPath);
|
|
history.pushState({ subpath: newPath }, '', newPath ? '/path/' + newPath : '/');
|
|
});
|
|
});
|
|
|
|
// File play link clicks.
|
|
document.querySelectorAll('.play-file').forEach(link => {
|
|
link.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
const fileType = this.getAttribute('data-file-type');
|
|
const relUrl = this.getAttribute('data-url');
|
|
if (fileType === 'music') {
|
|
const mediaUrl = '/media/' + relUrl;
|
|
const audioPlayer = document.getElementById('globalAudio');
|
|
audioPlayer.src = mediaUrl;
|
|
audioPlayer.load();
|
|
audioPlayer.play();
|
|
document.getElementById('nowPlayingInfo').textContent = relUrl;
|
|
document.querySelector('footer').style.display = 'flex';
|
|
} else if (fileType === 'image') {
|
|
// Open gallery modal via gallery.js function.
|
|
openGalleryModal(relUrl);
|
|
}
|
|
});
|
|
});
|
|
|
|
// Transcript icon clicks.
|
|
document.querySelectorAll('.show-transcript').forEach(link => {
|
|
link.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
const url = this.getAttribute('data-url');
|
|
fetch(url)
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error('Network response was not ok');
|
|
}
|
|
return response.text();
|
|
})
|
|
.then(data => {
|
|
document.getElementById('transcriptContent').innerHTML = marked.parse(data);
|
|
document.getElementById('transcriptModal').style.display = 'block';
|
|
})
|
|
.catch(error => {
|
|
document.getElementById('transcriptContent').innerHTML = '<p>Error loading transcription.</p>';
|
|
document.getElementById('transcriptModal').style.display = 'block';
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
// Modal close logic for transcript modal.
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const closeBtn = document.querySelector('#transcriptModal .close');
|
|
closeBtn.addEventListener('click', function () {
|
|
document.getElementById('transcriptModal').style.display = 'none';
|
|
});
|
|
window.addEventListener('click', function (event) {
|
|
if (event.target == document.getElementById('transcriptModal')) {
|
|
document.getElementById('transcriptModal').style.display = 'none';
|
|
}
|
|
});
|
|
|
|
// Load initial directory based on URL.
|
|
let initialSubpath = '';
|
|
if (window.location.pathname.indexOf('/path/') === 0) {
|
|
initialSubpath = window.location.pathname.substring(6); // remove "/path/"
|
|
}
|
|
loadDirectory(initialSubpath);
|
|
});
|
|
|
|
// Handle back/forward navigation.
|
|
window.addEventListener('popstate', function (event) {
|
|
const subpath = event.state ? event.state.subpath : '';
|
|
loadDirectory(subpath);
|
|
});
|