Move rarely used video actions into a More actions sheet

This commit is contained in:
Claude
2026-10-01 20:55:04 +00:00
parent 47826536a6
commit 88f878b8eb
3 changed files with 64 additions and 4 deletions

View File

@@ -2525,6 +2525,37 @@ async function offerPeerDownload(videoObj) {
els.playerPane.appendChild(btn);
}
// "More actions" sheet: the everyday four stay on the page, the rest live here.
// Each row drives the original (hidden) button, so handlers and the hidden /
// disabled state those buttons already manage keep working.
function openMoreActions() {
const defs = [
['editBtn', '✂', 'Edit and download', 'Trim a clip, adjust quality and export'],
['shareMomentBtn', '🔗', 'Share moment', 'Link, GIF or soundbite of this exact second'],
['externalBtn', '📺', 'Open in…', 'VLC, MX Player or another app'],
['brokenBtn', '⚠', 'Report broken video', 'Won’t play, out of sync or glitchy — re-download it', true],
];
const list = document.createElement('div');
list.className = 'more-list';
for (const [id, icon, title, sub, danger] of defs) {
const src = $(id);
if (!src || src.hidden) continue;
const row = document.createElement('button');
row.type = 'button';
row.className = 'more-row' + (danger ? ' danger' : '');
row.disabled = !!src.disabled;
row.innerHTML = '<span class="more-ico"></span><span class="more-txt"><b></b><small></small></span><span class="more-go">›</span>';
row.querySelector('.more-ico').textContent = icon;
row.querySelector('b').textContent = title;
row.querySelector('small').textContent = sub;
row.onclick = () => { closeModal(); setTimeout(() => src.click(), 0); };
list.appendChild(row);
}
if (!list.children.length) { toast('No more actions for this video'); return; }
showModal('More actions', list, [{ label: 'Close', onClick: closeModal }]);
}
// Reflect cache state on the now-playing Save button.
function updateNowPlayingActions() {
if (!current || !current.meta) return;
@@ -9350,6 +9381,7 @@ document.querySelectorAll('.chip').forEach((c) => {
await preload(current.meta);
}
});
if ($('moreBtn')) $('moreBtn').addEventListener('click', openMoreActions);
if ($('exportBtn')) $('exportBtn').addEventListener('click', () => { if (current && current.meta) exportToDevice(current.meta); });
els.addPlaylistBtn.addEventListener('click', () => {
if (current && current.meta) openCardMenu(current.meta);

View File

@@ -236,12 +236,15 @@
<div class="np-actions">
<button id="queueBtn" class="np-btn" title="Add to the temporary queue">+ Queue</button>
<button id="saveBtn" class="np-btn" title="Save this video for offline playback">⬇ Save</button>
<button id="editBtn" class="np-btn" title="Cut parts out and save a custom edited copy">✂ Edit &amp; download</button>
<button id="exportBtn" class="np-btn" title="Save this video to your gallery, Files app or Downloads folder — works while streaming too">🖼 Gallery</button>
<button id="addPlaylistBtn" class="np-btn" title="Add to a playlist">+ Playlist</button>
<button id="shareMomentBtn" class="np-btn" title="Share a link or GIF of this exact moment">🔗 Share moment</button>
<button id="externalBtn" class="np-btn" title="Play this in VLC, MX Player or another app">📺 Open in…</button>
<button id="brokenBtn" class="np-btn" title="Video won't play or looks broken? Re-download the server's copy" hidden>⚠ Broken</button>
<div id="npMoreHost" class="np-more-host" hidden>
<button id="editBtn" class="np-btn" title="Cut parts out and save a custom edited copy">✂ Edit &amp; download</button>
<button id="shareMomentBtn" class="np-btn" title="Share a link or GIF of this exact moment">🔗 Share moment</button>
<button id="externalBtn" class="np-btn" title="Play this in VLC, MX Player or another app">📺 Open in…</button>
<button id="brokenBtn" class="np-btn" title="Video won't play or looks broken? Re-download the server's copy" hidden>⚠ Broken</button>
</div>
<button id="moreBtn" class="np-more" type="button" aria-haspopup="dialog"><span>⋯ More actions</span><small>Edit &amp; download · Share moment · Open in… · Report broken</small></button>
</div>
</div>

View File

@@ -422,3 +422,28 @@
border: 1px solid var(--line); background: var(--bg-3); color: var(--text);
}
@media (min-width: 900px) { #listActions button.la-icon { height: 44px; flex-basis: 44px; width: 44px; border-radius: 14px; } }
/* ---- More actions ---- */
#nowPlayingMeta .np-actions .np-more-host { display: none; }
#nowPlayingMeta .np-actions .np-more {
order: 5; flex: 1 1 100%; min-height: 54px; padding: 8px 16px;
display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 2px;
border-radius: 16px; border: 1px solid var(--line); background: transparent; color: var(--text); cursor: pointer; text-align: left;
}
.np-more span { font: 700 14px var(--ui); }
.np-more small { font: 400 12px var(--ui); color: var(--text-dim); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.np-more:hover { border-color: var(--accent); }
.more-list { display: grid; gap: 8px; min-width: min(420px, 80vw); }
.more-row {
display: flex; align-items: center; gap: 14px; width: 100%; padding: 12px 14px; text-align: left;
border-radius: 14px; border: 1px solid var(--line); background: var(--bg-3); color: var(--text); cursor: pointer;
}
.more-row:hover { border-color: var(--accent); }
.more-row[disabled] { opacity: 0.5; pointer-events: none; }
.more-ico { flex: none; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; background: var(--bg-1); font-size: 19px; }
.more-txt { flex: 1; min-width: 0; display: grid; gap: 2px; }
.more-txt b { font: 700 14px var(--ui); }
.more-txt small { font: 400 12px/1.3 var(--ui); color: var(--text-dim); }
.more-go { color: var(--text-dim); font-size: 22px; }
.more-row.danger b { color: #ff8a80; }
.more-row.danger .more-ico { background: rgba(255, 75, 50, 0.16); }