Polish download action buttons in Classic and Glass Stage
This commit is contained in:
11
frontend/download-actions.css
Normal file
11
frontend/download-actions.css
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Shared quiet controls; use each layout's existing surface and focus tokens. */
|
||||
:is(.dl-row,.download-job) .download-action { display:inline-flex; align-items:center; justify-content:center; flex:none; gap:8px; height:auto; min-height:44px; min-width:44px; padding:8px 14px; border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--bg-2); color:var(--text); font:600 13px var(--ui); line-height:1.4; cursor:pointer; white-space:nowrap; }
|
||||
:is(.dl-row,.download-job) .download-action:hover { background:var(--bg-3); border-color:var(--accent); }
|
||||
:is(.dl-row,.download-job) .download-action.danger { color:var(--accent); }
|
||||
:is(.dl-row,.download-job) .download-action:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
|
||||
:is(.dl-row,.download-job) .download-action:disabled { opacity:.5; cursor:not-allowed; }
|
||||
.download-action-icon { width:20px; height:20px; flex:none; fill:none; stroke:currentColor; stroke-width:1.9; stroke-linecap:round; stroke-linejoin:round; pointer-events:none; }
|
||||
html[data-layout="glass-stage"] :is(.dl-row,.download-job) .download-action { border-radius:18px; border-color:var(--glass-line); background:var(--tile); color:var(--text-2); box-shadow:none; }
|
||||
html[data-layout="glass-stage"] :is(.dl-row,.download-job) .download-action:hover { border-color:var(--glass-line); background:var(--tile-hi); color:var(--text); }
|
||||
html[data-layout="glass-stage"] :is(.dl-row,.download-job) .download-action.danger { color:var(--accent-bright); }
|
||||
html[data-layout="glass-stage"] :is(.dl-row,.download-job) .download-action:focus-visible { outline-color:var(--accent-bright); }
|
||||
24
frontend/download-actions.js
Normal file
24
frontend/download-actions.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/* One action control for the Downloads page and Settings download manager. */
|
||||
(function(root) {
|
||||
'use strict';
|
||||
const paths = {
|
||||
retry: '<path d="M3 11a9 9 0 1 1 2.6 7M3 3v8h8"/>',
|
||||
cancel: '<path d="m6 6 12 12M6 18 18 6"/>',
|
||||
pause: '<path d="M8 5v14M16 5v14"/>',
|
||||
resume: '<path d="m9 5 10 7-10 7z"/>',
|
||||
};
|
||||
function create(doc, action, title) {
|
||||
if (!paths[action]) throw new Error('Unknown download action');
|
||||
const label = action[0].toUpperCase() + action.slice(1);
|
||||
const button = doc.createElement('button'); button.type = 'button';
|
||||
button.className = `dl-act download-action${action === 'cancel' ? ' danger' : ''}`;
|
||||
button.setAttribute('aria-label', `${label} ${title}`);
|
||||
const icon = doc.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||
icon.setAttribute('viewBox', '0 0 24 24'); icon.setAttribute('aria-hidden', 'true'); icon.setAttribute('focusable', 'false');
|
||||
icon.classList.add('download-action-icon'); icon.innerHTML = paths[action];
|
||||
const text = doc.createElement('span'); text.textContent = label;
|
||||
button.append(icon, text); return button;
|
||||
}
|
||||
const api = { create };
|
||||
if (typeof module !== 'undefined' && module.exports) module.exports = api; else root.DownloadActions = api;
|
||||
})(globalThis);
|
||||
@@ -1,6 +1,7 @@
|
||||
/* Downloads page UI module. Grouped jobs, storage info, confirmed cancellation. */
|
||||
(function (root) {
|
||||
'use strict';
|
||||
const actionButtons = typeof module !== 'undefined' ? require('./download-actions.js') : root.DownloadActions;
|
||||
const errors = typeof module !== 'undefined' ? require('./download-errors.js') : root.DownloadErrors;
|
||||
|
||||
const bytes = n => {
|
||||
@@ -222,10 +223,7 @@
|
||||
acts.className = 'dl-actions';
|
||||
|
||||
if (isActive) {
|
||||
const pauseBtn = doc.createElement('button');
|
||||
pauseBtn.type = 'button';
|
||||
pauseBtn.className = 'dl-act';
|
||||
pauseBtn.textContent = 'Pause';
|
||||
const pauseBtn = actionButtons.create(doc, 'pause', job.title || job.id);
|
||||
pauseBtn.setAttribute('aria-label', `Pause ${job.title || job.id}`);
|
||||
pauseBtn.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
@@ -234,10 +232,7 @@
|
||||
};
|
||||
acts.appendChild(pauseBtn);
|
||||
} else if (isPaused) {
|
||||
const resumeBtn = doc.createElement('button');
|
||||
resumeBtn.type = 'button';
|
||||
resumeBtn.className = 'dl-act';
|
||||
resumeBtn.textContent = 'Resume';
|
||||
const resumeBtn = actionButtons.create(doc, 'resume', job.title || job.id);
|
||||
resumeBtn.setAttribute('aria-label', `Resume ${job.title || job.id}`);
|
||||
resumeBtn.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
@@ -246,10 +241,7 @@
|
||||
};
|
||||
acts.appendChild(resumeBtn);
|
||||
} else if (isFailed) {
|
||||
const retryBtn = doc.createElement('button');
|
||||
retryBtn.type = 'button';
|
||||
retryBtn.className = 'dl-act';
|
||||
retryBtn.textContent = 'Retry';
|
||||
const retryBtn = actionButtons.create(doc, 'retry', job.title || job.id);
|
||||
retryBtn.setAttribute('aria-label', `Retry ${job.title || job.id}`);
|
||||
retryBtn.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
@@ -259,10 +251,7 @@
|
||||
acts.appendChild(retryBtn);
|
||||
}
|
||||
|
||||
const cancelBtn = doc.createElement('button');
|
||||
cancelBtn.type = 'button';
|
||||
cancelBtn.className = 'dl-act danger';
|
||||
cancelBtn.textContent = 'Cancel';
|
||||
const cancelBtn = actionButtons.create(doc, 'cancel', job.title || job.id);
|
||||
cancelBtn.setAttribute('aria-label', `Cancel ${job.title || job.id}`);
|
||||
cancelBtn.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* Download controls and device storage accounting. */
|
||||
(function(root) {
|
||||
'use strict';
|
||||
const actionButtons = typeof module !== 'undefined' ? require('./download-actions.js') : root.DownloadActions;
|
||||
const errors = typeof module !== 'undefined' ? require('./download-errors.js') : root.DownloadErrors;
|
||||
const bytes = n => n >= 1073741824 ? `${(n / 1073741824).toFixed(1)} GB` : `${(n / 1048576).toFixed(1)} MB`;
|
||||
function breakdown(files, playlists) {
|
||||
@@ -29,7 +30,7 @@
|
||||
const progress = doc.createElement('progress'); progress.max = job.progress?.total || 1; if (job.progress?.total) progress.value = job.progress.received || 0; progress.setAttribute('aria-label', `Saving ${job.title || job.id}`);
|
||||
const actions = doc.createElement('div');
|
||||
for (const action of [...(['active', 'queued'].includes(job.status) ? ['pause'] : [job.status === 'failed' ? 'retry' : 'resume']), 'cancel']) {
|
||||
const button = doc.createElement('button'); button.type = 'button'; button.textContent = action[0].toUpperCase() + action.slice(1); button.setAttribute('aria-label', `${button.textContent} ${job.title || job.id}`); button.onclick = () => { adapter.action(job.id, action); signature = ''; paint(); }; actions.append(button);
|
||||
const button = actionButtons.create(doc, action, job.title || job.id); button.onclick = () => { adapter.action(job.id, action); signature = ''; paint(); }; actions.append(button);
|
||||
}
|
||||
row.append(title, status, progress, actions);
|
||||
if (job.error) errors.appendDetails(row, job.error);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
<link rel="stylesheet" href="theme-glass-panel.css" />
|
||||
<link rel="stylesheet" href="fullscreen-orientation.css" />
|
||||
<link rel="stylesheet" href="related-videos.css" />
|
||||
<link rel="stylesheet" href="download-actions.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
@@ -670,6 +671,7 @@
|
||||
<script src="direct-protocol.js"></script>
|
||||
<script src="direct-stream.js"></script>
|
||||
<script src="direct-media.js"></script>
|
||||
<script src="download-actions.js"></script>
|
||||
<script src="download-errors.js"></script>
|
||||
<script src="downloads.js"></script>
|
||||
<script src="downloads-page.js"></script>
|
||||
|
||||
@@ -96,6 +96,8 @@ const SHELL = [
|
||||
'/audio-continuity.js',
|
||||
'/fullscreen-orientation.js',
|
||||
'/fullscreen-orientation.css',
|
||||
'/download-actions.js',
|
||||
'/download-actions.css',
|
||||
'/download-errors.js',
|
||||
'/downloads.js',
|
||||
'/downloads-page.js',
|
||||
|
||||
Reference in New Issue
Block a user