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 = {
|
const state = {
|
||||||
currentType: 'videos',
|
currentType: 'videos',
|
||||||
currentFile: null,
|
currentFile: null,
|
||||||
filesData: null
|
filesData: null,
|
||||||
|
currentItemEl: null
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize
|
// 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) {
|
function renderFileTree(files, container = document.getElementById('fileBrowser'), depth = 0) {
|
||||||
if (depth === 0) {
|
if (depth === 0) {
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
|
|
@ -801,11 +868,15 @@
|
||||||
const icon = state.currentType === 'videos' ? '🎬' : '🎵';
|
const icon = state.currentType === 'videos' ? '🎬' : '🎵';
|
||||||
fileItem.innerHTML = `<span class="file-icon">${icon}</span><span>${name}</span>`;
|
fileItem.innerHTML = `<span class="file-icon">${icon}</span><span>${name}</span>`;
|
||||||
|
|
||||||
fileItem.addEventListener('click', () => {
|
fileItem.dataset.path = content;
|
||||||
playFile(content, name);
|
fileItem.dataset.name = name;
|
||||||
document.querySelectorAll('.file-item').forEach(f => f.classList.remove('active'));
|
|
||||||
fileItem.classList.add('active');
|
fileItem.addEventListener('click', () => {
|
||||||
});
|
// Play and mark active
|
||||||
|
playFile(content, name, fileItem);
|
||||||
|
setActiveFileItem(fileItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
container.appendChild(fileItem);
|
container.appendChild(fileItem);
|
||||||
}
|
}
|
||||||
|
|
@ -876,7 +947,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function playFile(path, name) {
|
function playFile(path, name, sourceItemEl = null) {
|
||||||
const playerContainer = document.getElementById('playerContainer');
|
const playerContainer = document.getElementById('playerContainer');
|
||||||
const nowPlaying = document.getElementById('nowPlaying');
|
const nowPlaying = document.getElementById('nowPlaying');
|
||||||
const nowPlayingTitle = document.getElementById('nowPlayingTitle');
|
const nowPlayingTitle = document.getElementById('nowPlayingTitle');
|
||||||
|
|
@ -891,6 +962,11 @@
|
||||||
mediaElement.controls = true;
|
mediaElement.controls = true;
|
||||||
mediaElement.autoplay = true;
|
mediaElement.autoplay = true;
|
||||||
|
|
||||||
|
// Keep track of which UI element launched playback (used for "next")
|
||||||
|
if (sourceItemEl) {
|
||||||
|
state.currentItemEl = sourceItemEl;
|
||||||
|
}
|
||||||
|
|
||||||
if (isVideo) {
|
if (isVideo) {
|
||||||
// Some browsers only populate audioTracks after metadata is available
|
// Some browsers only populate audioTracks after metadata is available
|
||||||
mediaElement.addEventListener('loadedmetadata', () => {
|
mediaElement.addEventListener('loadedmetadata', () => {
|
||||||
|
|
@ -929,6 +1005,12 @@
|
||||||
console.log('Media ready to play:', name);
|
console.log('Media ready to play:', name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mediaElement.addEventListener('ended', () => {
|
||||||
|
// Auto-advance to next item when current finishes
|
||||||
|
playNextItem();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// URL encode the path properly
|
// URL encode the path properly
|
||||||
const encodedPath = encodeURIComponent(path);
|
const encodedPath = encodeURIComponent(path);
|
||||||
mediaElement.src = `serve_media.php?file=${encodedPath}`;
|
mediaElement.src = `serve_media.php?file=${encodedPath}`;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue