Handle unlimited files

This commit is contained in:
Gabriel Augendre 2023-01-04 15:55:59 +01:00
parent 9a9d3b8533
commit 707a099e63
2 changed files with 78 additions and 24 deletions

View file

@ -1,6 +1,7 @@
const GLOBAL_TIMEOUT = 10000; const GLOBAL_TIMEOUT = 10000;
let connectionOk = true; let connectionOk = true;
let statusTimeout = null; let statusTimeout = null;
let selectedFile = "";
function play() { function play() {
console.log("Play..."); console.log("Play...");
@ -23,9 +24,9 @@ function volume(modifier) {
.catch(handleError); .catch(handleError);
} }
function loadStatus() { async function loadStatus() {
console.log("Status..."); console.log("Status...");
fetch("/status", { signal: AbortSignal.timeout(GLOBAL_TIMEOUT) }) return fetch("/status", { signal: AbortSignal.timeout(GLOBAL_TIMEOUT) })
.then(response => response.json()) .then(response => response.json())
.then(handleStatus) .then(handleStatus)
.catch(handleError); .catch(handleError);
@ -49,18 +50,18 @@ function handleStatus(data) {
location.reload(); location.reload();
} }
let dom = ""; if (data.files.selected != selectedFile) {
data.files.available.forEach((element, index) => { selectedFile = data.files.selected;
let className = "w3-blue"; document.querySelectorAll(".w3-green").forEach(element => {
if (index === data.files.selectedIndex) { element.classList.remove("w3-green");
className = "w3-green"; element.classList.add("w3-blue");
}
dom += `<button class="w3-button ${className}" onclick="selectFile('${element}')">${element}</button>`;
}); });
if (data.files.moreNotShown) { const previouslySelected = document.querySelector(`[data-name='${selectedFile}']`);
dom += `<button class="w3-button w3-gray" disabled="" title="D'autres fichiers sont disponibles">...</button>`; if (previouslySelected) {
previouslySelected.classList.remove("w3-blue");
previouslySelected.classList.add("w3-green");
}
} }
document.getElementById("available-files").innerHTML = dom;
document.getElementById("volume-current").innerText = data.volume.current; document.getElementById("volume-current").innerText = data.volume.current;
document.getElementById("volume-increase").disabled = !data.volume.canIncrease; document.getElementById("volume-increase").disabled = !data.volume.canIncrease;
@ -68,6 +69,40 @@ function handleStatus(data) {
statusTimeout = setTimeout(loadStatus, GLOBAL_TIMEOUT); statusTimeout = setTimeout(loadStatus, GLOBAL_TIMEOUT);
} }
async function listFiles(cursor=0) {
console.log("List files...");
return fetch(`/list-files?cursor=${cursor}`, { signal: AbortSignal.timeout(GLOBAL_TIMEOUT) })
.then(response => response.json())
.then(data => {
let dom = "";
data.files.forEach(element => {
if (!element) {
// Filter out null
return;
}
let className = "w3-blue";
if (element === selectedFile) {
className = "w3-green";
}
dom += `<button class="w3-button ${className}" data-name="${element}" onclick="selectFile('${element}')">${element}</button>`;
});
if (data.files.moreNotShown) {
dom += `<button class="w3-button w3-gray" disabled="" title="D'autres fichiers sont disponibles">...</button>`;
}
const availableFilesNode = document.getElementById("available-files");
if (cursor == 0) {
availableFilesNode.innerHTML = dom;
}
else {
availableFilesNode.innerHTML += dom;
}
if (data.next) {
return listFiles(data.next);
}
})
.catch(handleError);
}
function handleError(error) { function handleError(error) {
console.error(error); console.error(error);
clearTimeout(statusTimeout); clearTimeout(statusTimeout);
@ -78,6 +113,6 @@ function handleError(error) {
} }
(() => { (() => {
loadStatus(); loadStatus().then(() => listFiles());
statusTimeout = setTimeout(loadStatus, GLOBAL_TIMEOUT); statusTimeout = setTimeout(loadStatus, GLOBAL_TIMEOUT);
})(); })();

View file

@ -83,6 +83,7 @@ void play()
void onStop(AsyncWebServerRequest *request) void onStop(AsyncWebServerRequest *request)
{ {
Serial.println("Stop playing");
audio.stopSong(); audio.stopSong();
request->send(200); request->send(200);
} }
@ -98,40 +99,57 @@ void onStatus(AsyncWebServerRequest *request)
Serial.println("Status"); Serial.println("Status");
AsyncResponseStream *response = request->beginResponseStream("application/json"); AsyncResponseStream *response = request->beginResponseStream("application/json");
DynamicJsonDocument root(4096); StaticJsonDocument<96> root;
JsonObject files = root.createNestedObject("files"); root["files"]["selected"] = selectedFile.c_str();
files["selectedIndex"] = -1;
files["moreNotShown"] = false;
JsonObject volume = root.createNestedObject("volume"); JsonObject volume = root.createNestedObject("volume");
volume["current"] = currentVolume; volume["current"] = currentVolume;
volume["canDecrease"] = currentVolume > 0; volume["canDecrease"] = currentVolume > 0;
volume["canIncrease"] = currentVolume < 21; volume["canIncrease"] = currentVolume < 21;
JsonArray availableFiles = files.createNestedArray("available"); serializeJson(root, *response);
request->send(response);
}
void onListFiles(AsyncWebServerRequest *request)
{
Serial.print("List files cursor=");
int cursor = 0;
if (request->hasParam("cursor")) {
String s_cursor = request->getParam("cursor")->value();
cursor = s_cursor.toInt();
}
Serial.println(cursor);
AsyncResponseStream *response = request->beginResponseStream("application/json");
StaticJsonDocument<512> root;
root["next"] = -1;
JsonArray files = root.createNestedArray("files");
File music = SD.open("/"); File music = SD.open("/");
File file = music.openNextFile(); File file = music.openNextFile();
unsigned int index = 0; int index = 0;
while (file) while (file)
{ {
String fileName = file.name(); String fileName = file.name();
if (fileIsValid(fileName)) if (fileIsValid(fileName))
{ {
availableFiles.add(fileName);
if (fileName == selectedFile) {
files["selectedIndex"] = index;
}
index++; index++;
if (index >= cursor)
files.add(fileName);
} }
file.close(); file.close();
if (root.overflowed()) if (root.overflowed())
{ {
files["moreNotShown"] = true; root["next"] = index;
break; break;
} }
file = music.openNextFile(); file = music.openNextFile();
} }
if (root["next"] == -1) {
root.remove("next");
}
serializeJson(root, *response); serializeJson(root, *response);
request->send(response); request->send(response);
@ -316,6 +334,7 @@ void setup()
server.on("/play", HTTP_GET, onPlay); server.on("/play", HTTP_GET, onPlay);
server.on("/stop", HTTP_GET, onStop); server.on("/stop", HTTP_GET, onStop);
server.on("/status", HTTP_GET, onStatus); server.on("/status", HTTP_GET, onStatus);
server.on("/list-files", HTTP_GET, onListFiles);
server.on("/select-file", HTTP_POST, onSelectFile); server.on("/select-file", HTTP_POST, onSelectFile);
server.on("/change-volume", HTTP_POST, onChangeVolume); server.on("/change-volume", HTTP_POST, onChangeVolume);
server.on("/upload", HTTP_POST, onUpload, onUploadFile); server.on("/upload", HTTP_POST, onUpload, onUploadFile);