// 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 += `${crumb.name}`; if (index < data.breadcrumbs.length - 1) { breadcrumbHTML += `>`; } }); document.getElementById('breadcrumbs').innerHTML = breadcrumbHTML; let contentHTML = ''; // Render directories. if (data.directories.length > 0) { contentHTML += '
Error loading directory.
'; }); } // 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 = 'Error loading transcription.
'; 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); });