Skip to content

Commit 3870bb7

Browse files
fhirschmannclaude
andcommitted
feat: play/pause button in the RFID tab for the highlighted file
Add a play/pause button next to the file-tree controls in the RFID tab. It is enabled when a playable node (audio file, playlist or folder) is highlighted and plays it via /exploreraudio (folder -> playmode 5, playlist -> 11, single file -> 1), so a file can be played with one click instead of the right-click context menu. While playback is running the button mirrors the live play/pause state and toggles pause/resume. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f41bb72 commit 3870bb7

2 files changed

Lines changed: 61 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ neon logo that doubles as the SVG favicon ([`8d9725c`](../../commit/8d9725c)):
6868
| Full backup: export/import of all settings + RFID assignments as JSON, WiFi credentials optional | [`7f2e4ae`](../../commit/7f2e4ae) |
6969
| Equalizer profiles: dropdown presets (Flat / Music / Audiobook-Speech / Deep voices / Custom) on top of the 3-band tone control; speech presets cut bass and lift mids/highs so deep narrator voices stay intelligible, persisted in NVS. Profiles can also be assigned per file or directory (right-click in the file browser) — e.g. set the speech profile for all Bibi Blocksberg episodes at once. The active profile can be cycled with the bindable command **154** (button/RFID modifier) and set/reported via the MQTT topic `equalizer` (`flat`/`music`/`speech`/`voiceBoost`) | [`300b9dd`](../../commit/300b9dd) |
7070
| Blinking "OK" indicator next to the battery replaces the generic "action successful" toast | [`0870ccc`](../../commit/0870ccc) |
71+
| Play/pause button in the RFID tab plays the highlighted file/folder (and pauses running playback) | [`8d3d196`](../../commit/8d3d196) |
7172
| SD card cleanup: removes macOS metadata (`.DS_Store`, `._*`, Spotlight/Trashes) with one click | [`5f38a51`](../../commit/5f38a51) |
7273
| Live log: the log dialog refreshes every 2 s and follows the end of the log | [`d326faa`](../../commit/d326faa) |
7374
| Drag & drop: upload files by dropping them from the file manager onto the file tree | [`e4972fe`](../../commit/e4972fe) |

html/management.html

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,9 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
15211521
style="height:38px; width: 200px; border-bottom-left-radius: 0; border-top-left-radius: 0;"
15221522
id="filetreesearch" data-i18n="[placeholder]files.search.placeholder"
15231523
onsearch="searchFiles($(this).val())" onkeyup="searchFiles($(this).val())">
1524+
<button id="rfidPlayBtn" class="btn btn-primary float-end" onclick="playSelectedNode()"
1525+
disabled data-i18n="[title]files.context.play"><span id="rfidPlayIcon"
1526+
class="fas fa-play"></span></button>
15241527
<button id="cleansd" class="btn btn-warning float-end" data-bs-toggle="modal"
15251528
data-bs-target="#cleanSdModal" data-i18n="[title]files.clean.button"><span
15261529
class="fas fa-broom"></span></button>
@@ -2609,6 +2612,53 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
26092612
}
26102613
/* File Explorer functions begin*/
26112614
var lastSelectedNodePath = "";
2615+
// currently highlighted playable node in the file tree (for the RFID-tab play button)
2616+
var rfidSelectedNode = null;
2617+
// mirror of the live playback state (false = paused/idle, true = playing)
2618+
var rfidIsPlaying = false;
2619+
// path that was last started via the RFID-tab play button
2620+
var rfidPlayingPath = null;
2621+
2622+
// True when the highlighted node is exactly the file that was started here.
2623+
function rfidSelectionIsCurrent() {
2624+
return rfidSelectedNode && rfidPlayingPath && rfidSelectedNode.path === rfidPlayingPath;
2625+
}
2626+
2627+
// The button is a play button by default; it only turns into a pause button
2628+
// while the highlighted file is the one actually playing. Selecting another
2629+
// file turns it back into a play button.
2630+
function updateRfidPlayButton() {
2631+
var btn = document.getElementById('rfidPlayBtn');
2632+
if (!btn) return;
2633+
var icon = document.getElementById('rfidPlayIcon');
2634+
if (rfidSelectionIsCurrent() && rfidIsPlaying) {
2635+
icon.className = 'fas fa-pause';
2636+
btn.disabled = false;
2637+
} else {
2638+
icon.className = 'fas fa-play';
2639+
btn.disabled = !rfidSelectedNode;
2640+
}
2641+
}
2642+
2643+
// Click handler for the RFID-tab play button: when the highlighted file is the
2644+
// current one, toggle pause/resume; otherwise start playback of the highlighted
2645+
// file/folder/playlist.
2646+
function playSelectedNode() {
2647+
if (!rfidSelectedNode) return;
2648+
if (rfidSelectionIsCurrent()) {
2649+
sendControl(170); // toggle pause/resume of the running playback
2650+
return;
2651+
}
2652+
var playMode = 1;
2653+
if (rfidSelectedNode.directory) {
2654+
playMode = 5;
2655+
} else if ((/\.(m3u|m3u8|asx|pls)$/i).test(rfidSelectedNode.path)) {
2656+
playMode = 11;
2657+
}
2658+
postData("http://" + host + "/exploreraudio?path=" + encodeURIComponent(rfidSelectedNode.path) + "&playmode=" + playMode);
2659+
rfidPlayingPath = rfidSelectedNode.path;
2660+
}
2661+
26122662
$('#explorerTree').on('select_node.jstree', function (e, data) {
26132663
$('input[name=fileOrUrl]').val(data.node.data.path);
26142664
if (ActiveSubTab !== 'rfid-music-tab') {
@@ -2624,6 +2674,13 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
26242674
$('.option-folder').hide();
26252675
$('#playMode option').removeAttr('selected').filter('[value=1]').attr('selected', true);
26262676
}
2677+
// remember the highlighted node so the RFID-tab play button can play it
2678+
if (["folder", "audio", "playlist"].includes(data.node.type)) {
2679+
rfidSelectedNode = { path: data.node.data.path, directory: data.node.data.directory, type: data.node.type };
2680+
} else {
2681+
rfidSelectedNode = null;
2682+
}
2683+
updateRfidPlayButton();
26272684
if (lastSelectedNodePath != data.node.data.path) {
26282685
if (data.node.data.directory) {
26292686
var ref = $('#explorerTree').jstree(true),
@@ -3408,6 +3465,9 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
34083465
} else {
34093466
btnTrackPlayPause.innerHTML = '<i id="ico-play-pause" class="fas fa-lg fa-pause"></i>';
34103467
}
3468+
// mirror playback state onto the RFID-tab play/pause button
3469+
rfidIsPlaying = !socketMsg.trackinfo.pausePlay;
3470+
updateRfidPlayButton();
34113471
var btnTrackFirst = document.getElementById('nav-btn-first');
34123472
var btnTrackPrev = document.getElementById('nav-btn-prev');
34133473
if (socketMsg.trackinfo.currentTrackNumber <= 1) {

0 commit comments

Comments
 (0)