Adds feature to automatically play next media in folder/directory
This commit is contained in:
parent
5f7b1aa7c1
commit
829b8990a1
1 changed files with 89 additions and 7 deletions
96
index.php
96
index.php
|
|
@ -639,7 +639,8 @@
|
|||
const state = {
|
||||
currentType: 'videos',
|
||||
currentFile: null,
|
||||
filesData: null
|
||||
filesData: null,
|
||||
currentItemEl: null
|
||||
};
|
||||
|
||||
// Initialize
|
||||
|
|
@ -766,6 +767,72 @@
|
|||
}
|
||||
}
|
||||
|
||||
function setActiveFileItem(fileItemEl) {
|
||||
// Clear existing "active" state
|
||||
document.querySelectorAll('.file-item').forEach(f => f.classList.remove('active'));
|
||||
|
||||
// Set new "active"
|
||||
if (fileItemEl) {
|
||||
fileItemEl.classList.add('active');
|
||||
fileItemEl.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
||||
}
|
||||
|
||||
state.currentItemEl = fileItemEl || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the "next" file-item in UI order, preferring the same folder/div
|
||||
* the current item is in. If there's no next sibling, it walks up the DOM
|
||||
* and continues searching.
|
||||
*/
|
||||
function findNextFileItem(currentEl) {
|
||||
if (!currentEl) return null;
|
||||
|
||||
// 1) Prefer "next siblings" within the same container
|
||||
let n = currentEl.nextElementSibling;
|
||||
while (n) {
|
||||
if (n.classList && n.classList.contains('file-item')) return n;
|
||||
n = n.nextElementSibling;
|
||||
}
|
||||
|
||||
// 2) If none, walk upward and look for the next file-item after the
|
||||
// parent container (e.g., next folder section)
|
||||
let parent = currentEl.parentElement;
|
||||
while (parent) {
|
||||
// Stop at the file browser root
|
||||
if (parent.id === 'fileBrowser') break;
|
||||
|
||||
let pNext = parent.nextElementSibling;
|
||||
while (pNext) {
|
||||
// If the next sibling is a file-item, play it
|
||||
if (pNext.classList && pNext.classList.contains('file-item')) return pNext;
|
||||
|
||||
// If it's a folder, search inside it for the first file-item
|
||||
const inside = pNext.querySelector && pNext.querySelector('.file-item');
|
||||
if (inside) return inside;
|
||||
|
||||
pNext = pNext.nextElementSibling;
|
||||
}
|
||||
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
|
||||
// No next item found
|
||||
return null;
|
||||
}
|
||||
|
||||
function playNextItem() {
|
||||
const next = findNextFileItem(state.currentItemEl);
|
||||
if (!next) {
|
||||
console.log('Reached end of list; no next item.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger the same behavior as clicking it
|
||||
next.click();
|
||||
}
|
||||
|
||||
|
||||
function renderFileTree(files, container = document.getElementById('fileBrowser'), depth = 0) {
|
||||
if (depth === 0) {
|
||||
container.innerHTML = '';
|
||||
|
|
@ -801,11 +868,15 @@
|
|||
const icon = state.currentType === 'videos' ? '🎬' : '🎵';
|
||||
fileItem.innerHTML = `<span class="file-icon">${icon}</span><span>${name}</span>`;
|
||||
|
||||
fileItem.addEventListener('click', () => {
|
||||
playFile(content, name);
|
||||
document.querySelectorAll('.file-item').forEach(f => f.classList.remove('active'));
|
||||
fileItem.classList.add('active');
|
||||
});
|
||||
fileItem.dataset.path = content;
|
||||
fileItem.dataset.name = name;
|
||||
|
||||
fileItem.addEventListener('click', () => {
|
||||
// Play and mark active
|
||||
playFile(content, name, fileItem);
|
||||
setActiveFileItem(fileItem);
|
||||
});
|
||||
|
||||
|
||||
container.appendChild(fileItem);
|
||||
}
|
||||
|
|
@ -876,7 +947,7 @@
|
|||
}
|
||||
|
||||
|
||||
function playFile(path, name) {
|
||||
function playFile(path, name, sourceItemEl = null) {
|
||||
const playerContainer = document.getElementById('playerContainer');
|
||||
const nowPlaying = document.getElementById('nowPlaying');
|
||||
const nowPlayingTitle = document.getElementById('nowPlayingTitle');
|
||||
|
|
@ -891,6 +962,11 @@
|
|||
mediaElement.controls = true;
|
||||
mediaElement.autoplay = true;
|
||||
|
||||
// Keep track of which UI element launched playback (used for "next")
|
||||
if (sourceItemEl) {
|
||||
state.currentItemEl = sourceItemEl;
|
||||
}
|
||||
|
||||
if (isVideo) {
|
||||
// Some browsers only populate audioTracks after metadata is available
|
||||
mediaElement.addEventListener('loadedmetadata', () => {
|
||||
|
|
@ -929,6 +1005,12 @@
|
|||
console.log('Media ready to play:', name);
|
||||
});
|
||||
|
||||
mediaElement.addEventListener('ended', () => {
|
||||
// Auto-advance to next item when current finishes
|
||||
playNextItem();
|
||||
});
|
||||
|
||||
|
||||
// URL encode the path properly
|
||||
const encodedPath = encodeURIComponent(path);
|
||||
mediaElement.src = `serve_media.php?file=${encodedPath}`;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue