Merge pull request 'Visual fixes' (#19) from visual_fixes into master

Reviewed-on: #19
This commit was merged in pull request #19.
This commit is contained in:
gru
2026-06-04 19:27:34 +02:00
9 changed files with 41 additions and 13 deletions
+1 -1
View File
@@ -1 +1 @@
export const footerStatusRefreshSource = " function rtorrentPairText(current, max){\n if(current == null) return '-';\n return max == null ? String(current) : `${current}/${max}`;\n }\n function footerStatusUpdatedText(s={}){\n const value=s.footer_updated_at || s.updated_at;\n if(!value) return '';\n const date=new Date(value);\n return Number.isNaN(date.getTime()) ? '' : ` · last known ${date.toLocaleString()}`;\n }\n function updateRtorrentFooterStats(s={}, cached=false){\n const suffix=cached ? footerStatusUpdatedText(s) : '';\n const sockets=rtorrentPairText(s.open_sockets, s.max_open_sockets);\n if($('statSockets')) $('statSockets').textContent=sockets;\n if($('statusSockets')) $('statusSockets').title=s.open_sockets == null ? `Open sockets unavailable${suffix}` : `Open rTorrent sockets${s.max_open_sockets == null ? '' : ' / max'}: ${sockets}${suffix}`;\n if($('statRtDownloads')) $('statRtDownloads').textContent=rtorrentPairText(s.active_downloads, s.max_downloads_global);\n if($('statusRtDownloads')) $('statusRtDownloads').title=`Active rTorrent downloads / max global downloads${suffix}`;\n if($('statRtUploads')) $('statRtUploads').textContent=rtorrentPairText(s.active_uploads, s.max_uploads_global);\n if($('statusRtUploads')) $('statusRtUploads').title=`Active rTorrent uploads / max global uploads${suffix}`;\n if($('statRtHttp')) $('statRtHttp').textContent=rtorrentPairText(s.open_http, s.max_open_http);\n if($('statusRtHttp')) $('statusRtHttp').title=`Open rTorrent HTTP connections / max HTTP connections${suffix}`;\n if($('statRtFiles')) $('statRtFiles').textContent=rtorrentPairText(s.open_files, s.max_open_files);\n if($('statusRtFiles')) $('statusRtFiles').title=`Open rTorrent files / max open files${suffix}`;\n if($('statRtPort')) $('statRtPort').textContent=(s.listen_port ?? '-') || '-';\n if($('statusRtPort')) $('statusRtPort').title=`rTorrent incoming port${suffix}`;\n if(cached){\n if(s.cpu!==undefined && $('statCpu')) $('statCpu').textContent=s.cpu;\n if(s.ram!==undefined && $('statRam')) $('statRam').textContent=s.ram;\n if(s.version!==undefined && $('statVersion')) $('statVersion').textContent=s.version || '-';\n if(s.down_rate_h!==undefined && $('statDl')) $('statDl').textContent=s.down_rate_h || '0 B/s';\n if(s.up_rate_h!==undefined && $('statUl')) $('statUl').textContent=s.up_rate_h || '0 B/s';\n if(s.down_rate_h!==undefined && $('mobileSpeedDl')) $('mobileSpeedDl').textContent=s.down_rate_h || '0 B/s';\n if(s.up_rate_h!==undefined && $('mobileSpeedUl')) $('mobileSpeedUl').textContent=s.up_rate_h || '0 B/s';\n updateBrowserSpeedTitle(s.down_rate_h, s.up_rate_h);\n }\n }\n function saveFooterStatusCache(s={}){\n const payload={\n open_sockets:s.open_sockets, max_open_sockets:s.max_open_sockets,\n active_downloads:s.active_downloads, max_downloads_global:s.max_downloads_global,\n active_uploads:s.active_uploads, max_uploads_global:s.max_uploads_global,\n open_http:s.open_http, max_open_http:s.max_open_http,\n open_files:s.open_files, max_open_files:s.max_open_files,\n listen_port:s.listen_port,\n cpu:s.cpu, ram:s.ram, version:s.version,\n down_rate_h:s.down_rate_h, up_rate_h:s.up_rate_h,\n footer_updated_at:new Date().toISOString()\n };\n try{ localStorage.setItem(FOOTER_STATUS_STORAGE_KEY, JSON.stringify(payload)); }catch(_){}\n }\n function restoreFooterStatusCache(){\n try{\n const cached=JSON.parse(localStorage.getItem(FOOTER_STATUS_STORAGE_KEY)||'null');\n if(cached && typeof cached==='object') updateRtorrentFooterStats(cached, true);\n }catch(_){}\n }\n async function refreshFooterStatusNow(){\n try{\n const res=await fetch('/api/system/status', {cache:'no-store'});\n const j=await res.json();\n const s=j.status||{};\n if(j.ok && s){\n updateRtorrentFooterStats(s, false);\n saveFooterStatusCache(s);\n applyFooterPreferences();\n }\n }catch(_){}\n }\n";
export const footerStatusRefreshSource = " function rtorrentPairText(current, max){\n if(current == null) return '-';\n return max == null ? String(current) : `${current}/${max}`;\n }\n function footerStatusUpdatedText(s={}){\n const value=s.footer_updated_at || s.updated_at;\n if(!value) return '';\n const date=new Date(value);\n return Number.isNaN(date.getTime()) ? '' : ` · last known ${date.toLocaleString()}`;\n }\n function updateRtorrentFooterStats(s={}, cached=false){\n const suffix=cached ? footerStatusUpdatedText(s) : '';\n const sockets=rtorrentPairText(s.open_sockets, s.max_open_sockets);\n if($('statSockets')) $('statSockets').textContent=sockets;\n if($('statusSockets')) $('statusSockets').title=s.open_sockets == null ? `Open sockets unavailable${suffix}` : `Open rTorrent sockets${s.max_open_sockets == null ? '' : ' / max'}: ${sockets}${suffix}`;\n if($('statRtDownloads')) $('statRtDownloads').textContent=rtorrentPairText(s.active_downloads, s.max_downloads_global);\n if($('statusRtDownloads')) $('statusRtDownloads').title=`Active rTorrent downloads / max global downloads${suffix}`;\n if($('statRtUploads')) $('statRtUploads').textContent=rtorrentPairText(s.active_uploads, s.max_uploads_global);\n if($('statusRtUploads')) $('statusRtUploads').title=`Active rTorrent uploads / max global uploads${suffix}`;\n if($('statRtHttp')) $('statRtHttp').textContent=rtorrentPairText(s.open_http, s.max_open_http);\n if($('statusRtHttp')) $('statusRtHttp').title=`Open rTorrent HTTP connections / max HTTP connections${suffix}`;\n if($('statRtFiles')) $('statRtFiles').textContent=rtorrentPairText(s.open_files, s.max_open_files);\n if($('statusRtFiles')) $('statusRtFiles').title=`Open rTorrent files / max open files${suffix}`;\n if($('statRtPort')) $('statRtPort').textContent=(s.listen_port ?? '-') || '-';\n if($('statusRtPort')) $('statusRtPort').title=`rTorrent incoming port${suffix}`;\n if(cached){\n if(s.cpu!==undefined && $('statCpu')) $('statCpu').textContent=s.cpu;\n if(s.ram!==undefined && $('statRam')) $('statRam').textContent=s.ram;\n if(s.version!==undefined && $('statVersion')) $('statVersion').textContent=s.version || '-';\n if(s.down_rate_h!==undefined && $('statDl')) $('statDl').textContent=s.down_rate_h || '0 B/s';\n if(s.up_rate_h!==undefined && $('statUl')) $('statUl').textContent=s.up_rate_h || '0 B/s';\n if(s.down_rate_h!==undefined && $('mobileSpeedDl')) $('mobileSpeedDl').textContent=s.down_rate_h || '0 B/s';\n if(s.up_rate_h!==undefined && $('mobileSpeedUl')) $('mobileSpeedUl').textContent=s.up_rate_h || '0 B/s';\n updateBrowserSpeedTitle(s.down_rate_h, s.up_rate_h);\n }\n }\n function saveFooterStatusCache(s={}){\n const payload={\n open_sockets:s.open_sockets, max_open_sockets:s.max_open_sockets,\n active_downloads:s.active_downloads, max_downloads_global:s.max_downloads_global,\n active_uploads:s.active_uploads, max_uploads_global:s.max_uploads_global,\n open_http:s.open_http, max_open_http:s.max_open_http,\n open_files:s.open_files, max_open_files:s.max_open_files,\n listen_port:s.listen_port,\n cpu:s.cpu, ram:s.ram, version:s.version,\n down_rate_h:s.down_rate_h, up_rate_h:s.up_rate_h,\n footer_updated_at:new Date().toISOString()\n };\n try{ localStorage.setItem(footerStatusStorageKey(), JSON.stringify(payload)); }catch(_){}\n }\n function restoreFooterStatusCache(){\n try{\n const cached=JSON.parse(localStorage.getItem(footerStatusStorageKey())||'null');\n if(cached && typeof cached==='object') updateRtorrentFooterStats(cached, true);\n }catch(_){}\n }\n async function refreshFooterStatusNow(){\n try{\n const res=await fetch('/api/system/status', {cache:'no-store'});\n const j=await res.json();\n const s=j.status||{};\n if(j.ok && s){\n updateRtorrentFooterStats(s, false);\n saveFooterStatusCache(s);\n applyFooterPreferences();\n }\n }catch(_){}\n }\n";
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
export const systemStatsSocketSource = " socket.on('system_stats',s=>{\n const usageAvailable=s.usage_available!==false && s.cpu!==undefined && s.ram!==undefined;\n $('statCpuBox')?.classList.toggle('d-none',!usageAvailable);\n $('statRamBox')?.classList.toggle('d-none',!usageAvailable);\n $('systemChart')?.classList.toggle('d-none',!usageAvailable);\n if(usageAvailable){\n $('statCpu').textContent=s.cpu??'-';\n $('statRam').textContent=s.ram??'-';\n drawSystemUsage(s.cpu,s.ram);\n }\n $('statVersion').textContent=s.version||'-';\n applyLiveSpeedStats(s);\n lastLimits={down:Number(s.down_limit||0),up:Number(s.up_limit||0)};\n $('statDlLimit').textContent=s.down_limit_h||'∞';\n $('statUlLimit').textContent=s.up_limit_h||'∞';\n $('statTotalDl').textContent=compactTransferText(s.total_down_h);\n $('statTotalUl').textContent=compactTransferText(s.total_up_h);\n updateSpeedPeaks(s.speed_peaks||{});\n drawTraffic(s.down_rate,s.up_rate);\n if(diskMonitorMode==='default'){\n drawDiskUsage(s.disk);\n }else{\n refreshUserDiskUsage(false);\n }\n updateRtorrentFooterStats(s, false);\n saveFooterStatusCache(s);\n if(s.poller) fillPoller(null,s.poller);\n applyFooterPreferences();\n });\n";
export const systemStatsSocketSource = " socket.on('system_stats',s=>{\n if(!isActiveProfilePayload(s)) return;\n const usageAvailable=s.usage_available!==false && s.cpu!==undefined && s.ram!==undefined;\n $('statCpuBox')?.classList.toggle('d-none',!usageAvailable);\n $('statRamBox')?.classList.toggle('d-none',!usageAvailable);\n $('systemChart')?.classList.toggle('d-none',!usageAvailable);\n if(usageAvailable){\n $('statCpu').textContent=s.cpu??'-';\n $('statRam').textContent=s.ram??'-';\n drawSystemUsage(s.cpu,s.ram);\n }\n $('statVersion').textContent=s.version||'-';\n applyLiveSpeedStats(s);\n lastLimits={down:Number(s.down_limit||0),up:Number(s.up_limit||0)};\n $('statDlLimit').textContent=s.down_limit_h||'∞';\n $('statUlLimit').textContent=s.up_limit_h||'∞';\n $('statTotalDl').textContent=compactTransferText(s.total_down_h);\n $('statTotalUl').textContent=compactTransferText(s.total_up_h);\n updateSpeedPeaks(s.speed_peaks||{});\n drawTraffic(s.down_rate,s.up_rate);\n if(diskMonitorMode==='default'){\n drawDiskUsage(s.disk);\n }else{\n refreshUserDiskUsage(false);\n }\n updateRtorrentFooterStats(s, false);\n saveFooterStatusCache(s);\n if(s.poller) fillPoller(null,s.poller);\n applyFooterPreferences();\n });\n";
+1 -1
View File
@@ -1 +1 @@
export const torrentRowRendererSource = " function statusMeta(t){\n const op=activeOperationFor(t);\n if(op) return {cls:'text-bg-info operation-status-badge', icon:actionIcon(op.action), color:'text-info', label:op.label};\n const status=String(t.status||'').toLowerCase();\n if(t.paused || status==='paused') return {cls:'text-bg-warning', icon:'fa-pause', color:'text-warning'};\n if(status==='checking' || Number(t.hashing||0)>0) return {cls:'text-bg-info', icon:'fa-rotate', color:'text-info'};\n if(status==='post-check' || t.post_check) return {cls:'text-bg-dark', icon:'fa-clipboard-check', color:'text-secondary', label:'Post-check'};\n if(status==='seeding') return {cls:'text-bg-success', icon:'fa-seedling', color:'text-success'};\n if(status==='downloading') return {cls:'text-bg-primary', icon:'fa-download', color:'text-primary'};\n if(status==='stopped') return {cls:'text-bg-secondary', icon:'fa-stop', color:'text-secondary'};\n return t.state ? {cls:'text-bg-success', icon:'fa-play', color:'text-success'} : {cls:'text-bg-secondary', icon:'fa-circle', color:'text-secondary'};\n }\n function statusBadge(t){ const m=statusMeta(t); return `<span class=\"badge status-badge ${m.cls}\"><i class=\"fa-solid ${m.icon} me-1\"></i>${esc(m.label || t.status)}</span>`; }\n function torrentErrorLog(t){\n // Note: The name-column status icon is useful only when the torrent has an error log to show in the tooltip.\n const status=String(t.status||'').trim().toLowerCase();\n const msg=String(t.message||'').trim();\n if(status==='error') return msg || 'Torrent reported an error.';\n if(!msg) return null;\n const patterns=['error','failed','failure','timeout','timed out','tracker','could not','cannot','refused','unreachable','denied'];\n return patterns.some(p=>msg.toLowerCase().includes(p)) ? msg : null;\n }\n function torrentNameStatusIcon(t){\n // Note: Non-error torrents keep the name cell clean; the Status column still shows their normal state.\n const errorLog=torrentErrorLog(t);\n return errorLog ? `<i class=\"fa-solid fa-triangle-exclamation torrent-warning-icon\" title=\"${esc(errorLog)}\" aria-label=\"Torrent error\"></i> ` : '';\n }\n function boolCell(value){ return Number(value||0) ? '<span class=\"badge text-bg-success\">yes</span>' : '<span class=\"badge text-bg-secondary\">no</span>'; }\n function renderRow(t){\n const labels=labelNames(t.label).map(l=>`<span class=\"chip label-mini\"><i class=\"fa-solid fa-tag\"></i> ${esc(l)}</span>`).join(' ');\n const errorLog=torrentErrorLog(t);\n const op=activeOperationFor(t);\n const classes=[selected.has(t.hash)?'selected':'', t.paused?'torrent-paused':'', op?'torrent-operating':'', errorLog?'torrent-warning':''].filter(Boolean).join(' ');\n const title=[t.name,errorLog,op?op.label:''].filter(Boolean).join('\\n');\n return `<tr data-hash=\"${esc(t.hash)}\" class=\"${classes}\">`+\n `<td data-col=\"select\" class=\"sel\"><input class=\"row-check\" type=\"checkbox\" ${selected.has(t.hash)?'checked':''}></td>`+\n `<td data-col=\"name\" class=\"name\" title=\"${esc(title)}\">${torrentNameStatusIcon(t)}${esc(t.name)}</td>`+\n `<td data-col=\"status\">${statusBadge(t)}</td>`+\n `<td data-col=\"size\">${esc(t.size_h)}</td>`+\n `<td data-col=\"progress\">${progress(t)}</td>`+\n `<td data-col=\"down_rate\">${esc(t.down_rate_h)}</td>`+\n `<td data-col=\"up_rate\">${esc(t.up_rate_h)}</td>`+\n `<td data-col=\"eta\">${esc(t.eta_h||\"-\")}</td>`+\n `<td data-col=\"seeds\">${esc(t.seeds)}</td>`+\n `<td data-col=\"peers\">${esc(t.peers)}</td>`+\n `<td data-col=\"ratio\">${esc(t.ratio)}</td>`+\n `<td data-col=\"path\" class=\"path\" title=\"${esc(t.path)}\">${esc(t.path)}</td>`+\n `<td data-col=\"label\">${labels||'<span class=\"text-muted\">-</span>'}</td>`+\n `<td data-col=\"ratio_group\">${esc(t.ratio_group||'')}</td>`+\n `<td data-col=\"down_total\">${esc(t.down_total_h||'-')}</td>`+\n `<td data-col=\"to_download\">${esc(t.to_download_h||'-')}</td>`+\n `<td data-col=\"up_total\">${esc(t.up_total_h||'-')}</td>`+\n `<td data-col=\"created\">${esc(formatDateTime(t.created))}</td>`+\n `<td data-col=\"last_activity\">${esc(formatDateTime(t.last_activity))}</td>`+\n `<td data-col=\"priority\">${esc(t.priority ?? '-')}</td>`+\n `<td data-col=\"state\">${boolCell(t.state)}</td>`+\n `<td data-col=\"active\">${boolCell(t.active)}</td>`+\n `<td data-col=\"complete\">${boolCell(t.complete)}</td>`+\n `<td data-col=\"hashing\">${esc(t.hashing ?? 0)}</td>`+\n `<td data-col=\"message\" class=\"message\" title=\"${esc(t.message||'')}\">${compactCell(t.message||'', 80)}</td>`+\n `<td data-col=\"hash\"><code>${esc(t.hash||'')}</code></td>`+\n `</tr>`;\n }\n\n\n\n\n";
export const torrentRowRendererSource = " function statusMeta(t){\n const op=activeOperationFor(t);\n if(op) return {cls:'text-bg-info operation-status-badge', icon:actionIcon(op.action), color:'text-info', label:op.label};\n const status=String(t.status||'').toLowerCase();\n if(t.paused || status==='paused') return {cls:'text-bg-warning', icon:'fa-pause', color:'text-warning'};\n if(status==='checking' || Number(t.hashing||0)>0) return {cls:'text-bg-info', icon:'fa-rotate', color:'text-info'};\n if(status==='post-check' || t.post_check) return {cls:'text-bg-dark', icon:'fa-clipboard-check', color:'text-secondary', label:'Post-check'};\n if(status==='seeding') return {cls:'text-bg-success', icon:'fa-seedling', color:'text-success'};\n if(status==='downloading') return {cls:'text-bg-primary', icon:'fa-download', color:'text-primary'};\n if(status==='stopped') return {cls:'text-bg-secondary', icon:'fa-stop', color:'text-secondary'};\n return t.state ? {cls:'text-bg-success', icon:'fa-play', color:'text-success'} : {cls:'text-bg-secondary', icon:'fa-circle', color:'text-secondary'};\n }\n function statusBadge(t){ const m=statusMeta(t); return `<span class=\"badge status-badge ${m.cls}\"><i class=\"fa-solid ${m.icon} me-1\"></i>${esc(m.label || t.status)}</span>`; }\n function torrentErrorLog(t){\n // Note: The name-column status icon is useful only when the torrent has an error log to show in the tooltip.\n const status=String(t.status||'').trim().toLowerCase();\n const msg=String(t.message||'').trim();\n if(status==='error') return msg || 'Torrent reported an error.';\n if(!msg) return null;\n const patterns=['error','failed','failure','timeout','timed out','tracker','could not','cannot','refused','unreachable','denied'];\n return patterns.some(p=>msg.toLowerCase().includes(p)) ? msg : null;\n }\n function torrentNameStatusIcon(t){\n // Note: Non-error torrents keep the name cell clean; the Status column still shows their normal state.\n const errorLog=torrentErrorLog(t);\n return errorLog ? `<i class=\"fa-solid fa-triangle-exclamation torrent-warning-icon\" title=\"${esc(errorLog)}\" aria-label=\"Torrent error\"></i> ` : '';\n }\n function boolCell(value){ return Number(value||0) ? '<span class=\"badge text-bg-success\">yes</span>' : '<span class=\"badge text-bg-secondary\">no</span>'; }\n function renderRow(t){\n const labels=labelNames(t.label).map(l=>`<span class=\"chip label-mini\"><i class=\"fa-solid fa-tag\"></i> ${esc(l)}</span>`).join(' ');\n const errorLog=torrentErrorLog(t);\n const op=activeOperationFor(t);\n const classes=[selected.has(t.hash)?'selected':'', t.paused?'torrent-paused':'', op?'torrent-operating':'', errorLog?'torrent-warning':''].filter(Boolean).join(' ');\n const title=[t.name,errorLog,op?op.label:''].filter(Boolean).join('\\n');\n return `<tr data-hash=\"${esc(t.hash)}\" class=\"${classes}\">`+\n `<td data-col=\"select\" class=\"sel\"><span class=\"torrent-select-cell\"><input class=\"row-check\" type=\"checkbox\" ${selected.has(t.hash)?'checked':''}></span></td>`+\n `<td data-col=\"name\" class=\"name\" title=\"${esc(title)}\">${torrentNameStatusIcon(t)}${esc(t.name)}</td>`+\n `<td data-col=\"status\">${statusBadge(t)}</td>`+\n `<td data-col=\"size\">${esc(t.size_h)}</td>`+\n `<td data-col=\"progress\">${progress(t)}</td>`+\n `<td data-col=\"down_rate\">${esc(t.down_rate_h)}</td>`+\n `<td data-col=\"up_rate\">${esc(t.up_rate_h)}</td>`+\n `<td data-col=\"eta\">${esc(t.eta_h||\"-\")}</td>`+\n `<td data-col=\"seeds\">${esc(t.seeds)}</td>`+\n `<td data-col=\"peers\">${esc(t.peers)}</td>`+\n `<td data-col=\"ratio\">${esc(t.ratio)}</td>`+\n `<td data-col=\"path\" class=\"path\" title=\"${esc(t.path)}\">${esc(t.path)}</td>`+\n `<td data-col=\"label\">${labels||'<span class=\"text-muted\">-</span>'}</td>`+\n `<td data-col=\"ratio_group\">${esc(t.ratio_group||'')}</td>`+\n `<td data-col=\"down_total\">${esc(t.down_total_h||'-')}</td>`+\n `<td data-col=\"to_download\">${esc(t.to_download_h||'-')}</td>`+\n `<td data-col=\"up_total\">${esc(t.up_total_h||'-')}</td>`+\n `<td data-col=\"created\">${esc(formatDateTime(t.created))}</td>`+\n `<td data-col=\"last_activity\">${esc(formatDateTime(t.last_activity))}</td>`+\n `<td data-col=\"priority\">${esc(t.priority ?? '-')}</td>`+\n `<td data-col=\"state\">${boolCell(t.state)}</td>`+\n `<td data-col=\"active\">${boolCell(t.active)}</td>`+\n `<td data-col=\"complete\">${boolCell(t.complete)}</td>`+\n `<td data-col=\"hashing\">${esc(t.hashing ?? 0)}</td>`+\n `<td data-col=\"message\" class=\"message\" title=\"${esc(t.message||'')}\">${compactCell(t.message||'', 80)}</td>`+\n `<td data-col=\"hash\"><code>${esc(t.hash||'')}</code></td>`+\n `</tr>`;\n }\n\n\n\n\n";
+33 -5
View File
@@ -6,7 +6,12 @@
--statusbar: calc(34px * var(--ui-scale));
--mobile-filterbar-height: 132px;
--sidebar: calc(270px * var(--ui-scale));
--torrent-progress-complete: #198754;
/* Note: Completed torrent progress follows Bootstrap success badges exactly. */
--torrent-progress-complete: var(--bs-success);
/* Note: Incomplete progress bars use theme-aware HSL tuning so light themes stay slightly more muted than dark themes. */
--torrent-progress-scale-saturation: 85;
--torrent-progress-scale-lightness-base: 23;
--torrent-progress-scale-lightness-range: 7;
--pytorrent-page-bg: var(--bs-body-bg);
--pytorrent-shell-shadow: 0 12px 45px rgba(0, 0, 0, 0.38);
}
@@ -21,8 +26,10 @@
--bs-secondary-color: #8d98aa;
--bs-primary-bg-subtle: #0d2238;
--bs-primary-text-emphasis: #9ecbff;
--torrent-progress-complete: #2f9e75;
--pytorrent-page-bg: var(--bs-body-bg);
--torrent-progress-scale-saturation: 48;
--torrent-progress-scale-lightness-base: 30;
--torrent-progress-scale-lightness-range: 5;
}
html[data-app-font="adwaita-mono"] {
@@ -411,6 +418,7 @@ body {
position: relative;
}
.torrent-table {
--torrent-row-height: 32px;
font-size: var(--torrent-list-font-size, 13px);
margin: 0;
white-space: nowrap;
@@ -434,7 +442,7 @@ body {
}
.torrent-table tbody tr {
cursor: default;
height: 32px;
height: var(--torrent-row-height);
}
.torrent-table > :not(caption) > * > * {
padding-bottom: 0.22rem;
@@ -449,8 +457,21 @@ body {
background: var(--bs-primary-bg-subtle);
}
.torrent-table .sel {
width: 34px;
padding-bottom: 0;
padding-top: 0;
text-align: center;
width: 34px;
}
.torrent-table .torrent-select-cell {
align-items: center;
display: flex;
height: var(--torrent-row-height);
justify-content: center;
}
.torrent-table .row-check {
display: block;
flex: 0 0 auto;
margin: 0;
}
.torrent-table .name {
overflow: hidden;
@@ -1374,6 +1395,9 @@ body.mobile-mode .mobile-card {
width 0.25s ease,
background-color 0.25s ease;
}
.torrent-progress.is-complete .progress-bar {
background: var(--torrent-progress-complete) !important;
}
.torrent-progress > span {
position: absolute;
inset: 0;
@@ -5466,8 +5490,12 @@ body,
}
/* Compact torrent list density. Font size is controlled only by the Torrent list font slider. */
body.compact-torrent-list .torrent-table {
--torrent-row-height: 24px;
}
body.compact-torrent-list .torrent-table tbody tr {
height: 24px;
height: var(--torrent-row-height);
}
body.compact-torrent-list .torrent-table > :not(caption) > * > * {