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

View file

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