i2psnark: Add js audio playlist controls

resurrected and completed from snark-playlist branch (2024)
This commit is contained in:
zzz committed 2026-09-02 15:01:38 -04:00
1 parent 10a804a988
commit 2c3fd2a953
2 files changed
+311 -1

No files matched your search

@@ -3419,6 +3419,7 @@ public class I2PSnarkServlet extends BasicServlet {
"<link rel=\"shortcut icon\" href=\"" + _themePath + "favicon.ico\">\n");
if (showPriority)
buf.append("<script src=\"").append(_contextPath).append(WARBASE + "js/folder.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>\n");
buf.append("<script src=\"").append(_contextPath).append(WARBASE + "js/playlist.js?" + CoreVersion.VERSION + "\" type=\"text/javascript\"></script>\n");
buf.append("</head><body>\n" +
"<center><div class=\"snarknavbar\"><a href=\"").append(_contextPath).append("/\" title=\"Torrents\"" +
" class=\"snarkNav nav_main\">");
@@ -4037,7 +4038,34 @@ public class I2PSnarkServlet extends BasicServlet {
// playlist button
if (hasCompleteAudio(fileList, storage, remainingArray)) {
buf.append("<tr><td colspan=\"" + (showPriority ? '5' : '4') + "\" class=\"ParentDir\">" +
// js play buttons
// js will initialize playall to control (visible)
buf.append("<tr><td class=\"snarkFileIcon\" colspan=\"2\">\n");
buf.append("<a class=\"controld script\" id=\"playall\" href=\"#\">")
.append(toThemeImg("start_all")).append(_t("Play All"))
.append("</a>\n");
//buf.append("<a class=\"controld script\" id=\"playprev\" href=\"#\">").append(toImg("cancel")).append(_t("Play Previous")).append("</a>\n");
String alt = _t("Play Previous");
buf.append("<a class=\"controld script\" id=\"playprev\" href=\"#\">")
.append(toThemeImg("previous", alt, alt))
.append("</a>\n");
//buf.append("<a class=\"controld script\" id=\"playpause\" href=\"#\">").append(toImg("cancel")).append(_t("Pause")).append("</a>\n");
alt = _t("Pause");
buf.append("<a class=\"controld script\" id=\"playpause\" href=\"#\">")
.append(toThemeImg("cancel", alt, alt))
.append("</a>\n");
//buf.append("<a class=\"controld script\" id=\"playresume\" href=\"#\">").append(toImg("cancel")).append(_t("Resume")).append("</a>\n");
alt = _t("Resume");
buf.append("<a class=\"controld script\" id=\"playresume\" href=\"#\">")
.append(toThemeImg("recheck", alt, alt))
.append("</a>\n");
//buf.append("<a class=\"controld script\" id=\"playnext\" href=\"#\">").append(toImg("cancel")).append(_t("Play Next")).append("</a>\n");
alt = _t("Play Next");
buf.append("<a class=\"controld script\" id=\"playnext\" href=\"#\">")
.append(toThemeImg("next", alt, alt))
.append("</a>\n");
buf.append("<span id=\"playing\"></span>\n");
buf.append("<td class=\"snarkFileSize\" colspan=\"" + (showPriority ? '3' : '2') + "\">" +
"<a href=\"").append(base).append("?playlist");
if (sortParam != null && !"0".equals(sortParam) && !"1".equals(sortParam))
buf.append("&amp;sort=").append(sortParam);
+282
View File
@@ -0,0 +1,282 @@
/* @license http://www.gnu.org/licenses/gpl-2.0.html GPL-2.0 */
/* see also licenses/LICENSE-GPLv2.txt */
var __i2psnark_isplaying = false;
var __i2psnark_autoplay = false;
var __i2psnark_playindex = -1;
var __i2psnark_playsize = 0;
// note that we use currentTime = 0, not fastSeek(0), because
// Chrome doesn't support it.
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
const setupplaybuttons=()=>{
let button = document.getElementById('playall');
if (button === null)
return;
const audios = document.getElementsByClassName("audio");
__i2psnark_playsize = audios.length;
for (var i = 0; i < __i2psnark_playsize; i++) {
const audio = audios[i];
audio.addEventListener("ended", function() {
audioended();
});
audio.addEventListener("pause", function() {
audiopause();
});
audio.addEventListener("play", function() {
audioplay();
});
}
// all buttons start disabled (controld)
if (__i2psnark_playsize > 1) {
button.addEventListener("click", function() {
playall();
event.preventDefault();
});
button.classList.remove("controld");
button.classList.add("control");
}
button = document.getElementById('playpause');
button.disabled = true;
if (__i2psnark_playsize > 1) {
button.addEventListener("click", function() {
playpause();
event.preventDefault();
});
}
button = document.getElementById('playprev');
if (__i2psnark_playsize > 1) {
button.disabled = true;
button.addEventListener("click", function() {
playprev();
event.preventDefault();
});
}
button = document.getElementById('playnext');
if (__i2psnark_playsize > 1) {
button.addEventListener("click", function() {
playnext();
event.preventDefault();
});
}
button = document.getElementById('playresume');
if (__i2psnark_playsize > 1) {
button.addEventListener("click", function() {
playresume();
event.preventDefault();
});
}
}
// buttons
const playprev=()=>{
let idx = __i2psnark_playindex;
if (idx <= 0)
return;
__i2psnark_playindex--;
const audios = document.getElementsByClassName("audio");
if (__i2psnark_isplaying) {
audios[idx].pause();
audios[idx].currentTime = 0;
}
audios[__i2psnark_playindex].currentTime = 0;
audios[__i2psnark_playindex].play();
playing();
}
const playnext=()=>{
let idx = __i2psnark_playindex;
if (idx >= __i2psnark_playsize - 1)
return;
__i2psnark_playindex++;
const audios = document.getElementsByClassName("audio");
if (__i2psnark_isplaying) {
audios[idx].pause();
audios[idx].currentTime = 0;
}
audios[__i2psnark_playindex].currentTime = 0;
audios[__i2psnark_playindex].play();
playing();
}
const playpause=()=>{
__i2psnark_autoplay = false;
if (!__i2psnark_isplaying)
return;
const audios = document.getElementsByClassName("audio");
audios[__i2psnark_playindex].pause();
notplaying();
}
const playall=()=>{
__i2psnark_autoplay = true;
if (__i2psnark_isplaying)
return;
__i2psnark_playindex = 0;
const audios = document.getElementsByClassName("audio");
for (var i = 0; i < __i2psnark_playsize; i++) {
audios[i].pause();
audios[i].currentTime = 0;
}
audios[0].play();
playing();
}
const playresume=()=>{
__i2psnark_autoplay = true;
if (__i2psnark_isplaying)
return;
if (__i2psnark_playindex >= __i2psnark_playsize - 1 || __i2psnark_playindex < 0)
__i2psnark_playindex = 0;
const audios = document.getElementsByClassName("audio");
// start where we were before
audios[__i2psnark_playindex].play();
playing();
}
// events
const audioended=()=>{
//console.warn("audioended");
const audio = event.target;
audio.currentTime = 0;
let span = document.getElementById('playing');
span.textContent = "";
__i2psnark_playindex = Number(audio.getAttribute("audioindex"));
if (__i2psnark_playindex < __i2psnark_playsize - 1) {
__i2psnark_playindex++;
if (__i2psnark_autoplay) {
const audios = document.getElementsByClassName("audio");
audios[__i2psnark_playindex].play();
// TODO translate
span.textContent = "Now playing: " + audio.getAttribute("audioname");
playing();
} else {
notplaying();
}
} else {
__i2psnark_playindex = -1;
notplaying();
}
}
const audiopause=()=>{
const audio = event.target;
let idx = Number(audio.getAttribute("audioindex"));
if (idx != __i2psnark_playindex) {
// ignore unless this is the current one playing
//console.warn("audiopause ignored");
return;
}
//console.warn("audiopause");
let span = document.getElementById('playing');
// TODO translate
span.textContent = "Paused: " + audio.getAttribute("audioname");
notplaying();
}
const audioplay=()=>{
//console.warn("audioplay");
const audio = event.target;
__i2psnark_playindex = Number(audio.getAttribute("audioindex"));
let span = document.getElementById('playing');
// TODO translate
span.textContent = "Now playing: " + audio.getAttribute("audioname");
const audios = document.getElementsByClassName("audio");
// prevent two at once
for (var i = 0; i < __i2psnark_playsize; i++) {
if (i != __i2psnark_playindex) {
audios[i].pause();
audios[i].currentTime = 0;
}
}
playing();
}
// state changes
const playing=()=>{
__i2psnark_isplaying = true;
let button = document.getElementById('playprev');
if (__i2psnark_playindex > 0) {
button.disabled=false;
button.classList.remove("controld");
button.classList.add("control");
} else {
button.disabled=true;
button.classList.remove("control");
button.classList.add("controld");
}
button = document.getElementById('playnext');
if (__i2psnark_playindex < __i2psnark_playsize - 1) {
button.disabled=false;
button.classList.remove("controld");
button.classList.add("control");
} else {
button.disabled=true;
button.classList.remove("control");
button.classList.add("controld");
}
button = document.getElementById('playall');
button.disabled=true;
button.classList.remove("control");
button.classList.add("controld");
button = document.getElementById('playpause');
button.disabled=false;
button.classList.remove("controld");
button.classList.add("control");
button = document.getElementById('playresume');
button.disabled=true;
button.classList.remove("control");
button.classList.add("controld");
}
const notplaying=()=>{
__i2psnark_isplaying = false;
let button = document.getElementById('playprev');
if (__i2psnark_playindex > 0) {
button.disabled=false;
button.classList.remove("controld");
button.classList.add("control");
} else {
button.disabled=true;
button.classList.remove("control");
button.classList.add("controld");
}
button = document.getElementById('playnext');
if (__i2psnark_playindex < __i2psnark_playsize - 1) {
button.disabled=false;
button.classList.remove("controld");
button.classList.add("control");
} else {
button.disabled=true;
button.classList.remove("control");
button.classList.add("controld");
}
button = document.getElementById('playall');
button.disabled=false;
button.classList.remove("controld");
button.classList.add("control");
button = document.getElementById('playpause');
button.disabled=true;
button.classList.remove("control");
button.classList.add("controld");
button = document.getElementById('playresume');
if (__i2psnark_playindex >= 0) {
button.disabled=false;
button.classList.remove("controld");
button.classList.add("control");
} else {
button.disabled=true;
button.classList.remove("control");
button.classList.add("controld");
}
}
document.addEventListener("DOMContentLoaded", function() {
setupplaybuttons();
}, true);
/* @license-end */