Files pane plays through the player bar, once

The pane drew its own <audio controls> for a downloaded file, and its
onplay also started the player bar, so one click played the same file
twice at once. The pane now has a play button (with the file's type
icon, like the other rows) that hands that exact file to the player
bar, the only player. play() takes the file, so another of an item's
files starts from its top instead of resuming the first. Dead CSS for
the pane's <audio> removed.

Test: play in the Files pane leaves one <audio> on the page, the bar's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0173mGu6rK18Ne7UGTwAaVJV
This commit is contained in:
2026-09-11 17:30:03 +00:00
parent 5362436766
commit 669e8b5124
3 changed files with 29 additions and 18 deletions

View File

@@ -191,7 +191,6 @@ input:focus,select:focus{outline:0;border-color:var(--accent)}
/* The selected item's files, beside the list, as the original's Files pane was. */
#files{grid-area:files;overflow-y:auto;padding:8px 12px;border-left:1px solid var(--line);background:var(--panel)}
#files .encbox{margin-top:8px}
#files .encbox audio{min-width:0;width:100%;flex-basis:100%}
#files .empty{padding:24px 0}
.fhd{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--faint)}
#grab{grid-area:grab;cursor:row-resize;background:var(--line)}
@@ -208,7 +207,6 @@ input:focus,select:focus{outline:0;border-color:var(--accent)}
display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:14px;
padding:10px 12px;border:1px solid var(--line);border-radius:9px;background:var(--panel2);
}
.encbox audio{flex:1;min-width:200px;margin:0}
.fhead{display:flex;gap:18px;margin-bottom:18px}
.fhead .art{width:118px;height:118px;font-size:34px;box-shadow:var(--shadow)}
.fhead .meta{min-width:0;flex:1;display:flex;flex-direction:column}
@@ -1192,13 +1190,9 @@ function showDetail(e){
$('#dback').onclick=()=>showDetail(null);
for(const root of [box,files]) if(root) $$('button[data-a]',root).forEach(b=>
b.onclick=()=>epAction(b.dataset.a,e,null,b.dataset.enc?Number(b.dataset.enc):null));
for(const x of e.enclosures){
const a=$(`#audio-${x.id}`);
if(a) a.onplay=()=>play(e);
}
}
/// One enclosure: a player when the file is here, otherwise what it is and a way to get it.
/// One enclosure: a play button when the file is here, otherwise what it is and a way to get it.
function encBox(x){
const size=x.length?mb(x.length):'';
// One file serves everyone reading the feed, so deleting is not a private act.
@@ -1221,9 +1215,12 @@ function encBox(x){
</div>`;
}
if(x.path){
// One player, the bar at the bottom. This pane had an <audio> of its own, and playing it
// started the bar as well, so the same file played twice at once.
return `<div class="encbox">
<audio id="audio-${x.id}" controls preload="none" src="/media/${x.id}"></audio>
<span class="meta">${size}</span>
${kindIcon(x)}
<span class="meta" style="flex:1">${size}</span>
<button class="btn ico" data-a="play" data-enc="${x.id}" title="Play" aria-label="Play">${ICON.play}</button>
${saveBtn}
${delBtn}
</div>`;
@@ -1247,7 +1244,7 @@ async function epAction(a,e,el,encId){
const enc=(encId!=null && e.enclosures.find(x=>x.id===encId)) || e.enclosures[0];
const path=`/api/entries/${encodeURIComponent(e.feed_id)}/${encodeURIComponent(e.guid)}`;
try{
if(a==='play') play(e);
if(a==='play') play(e, encId!=null ? enc : undefined);
if(a==='flag'){ e.flagged=!e.flagged; await api(path+'/flags',{method:'POST',body:JSON.stringify({flagged:e.flagged})}); redraw(); }
if(a==='read'){ e.read=!e.read; await api(path+'/flags',{method:'POST',body:JSON.stringify({read:e.read})}); redraw(); loadFeeds(true); }
if(a==='get'){
@@ -1294,15 +1291,16 @@ function markPlayed(){
{method:'POST',body:JSON.stringify({read:true})}).then(()=>loadFeeds(true)).catch(()=>{});
}
function play(e){
const enc=e.enclosures.find(isPlayable);
if(!enc){
/// Plays one of the item's files in the player bar: the one asked for, or its first playable one.
function play(e,enc=e.enclosures.find(isPlayable)){
if(!isPlayable(enc)){
toast(e.enclosures.some(x=>x.path) ? 'That file is not audio or video' : 'Not downloaded yet', true);
return;
}
const resuming = player.guid===e.guid;
// The same file carries on where it was; another of the item's files starts from its top.
const resuming = player.guid===e.guid && player.enc===enc.id;
if(!resuming){
player.guid=e.guid; player.feed=e.feed_id; player.entry=e;
player.guid=e.guid; player.feed=e.feed_id; player.entry=e; player.enc=enc.id;
audio.src=`/media/${enc.id}`;
audio.currentTime=0;
if(e.position>5) audio.addEventListener('loadedmetadata',()=>{audio.currentTime=e.position},{once:true});