From dce515f37cdbd92b7b12158c82add7382e053909 Mon Sep 17 00:00:00 2001 From: Rukario Date: Wed, 30 Oct 2024 07:19:01 -0700 Subject: [PATCH] feat: display percent in progress bar for web client (#5937) * Update transmission-app.scss * Update torrent-row.js * Update transmission-app.scss * Update transmission-app.scss * Update transmission-app.scss * Update transmission-app.scss Co-authored-by: Yat Ho * Update file-row.js Co-authored-by: Yat Ho * Update formatter.js Co-authored-by: Yat Ho * Update inspector.js Co-authored-by: Yat Ho * Update torrent-row.js Co-authored-by: Yat Ho * Update torrent.js Co-authored-by: Yat Ho * Update transmission-app.scss * Update transmission-app.scss --------- Co-authored-by: Yat Ho --- web/assets/css/transmission-app.scss | 154 +++++++++++++++++---------- web/src/file-row.js | 1 + web/src/formatter.js | 6 +- web/src/inspector.js | 4 +- web/src/torrent-row.js | 8 +- web/src/torrent.js | 2 +- 6 files changed, 109 insertions(+), 66 deletions(-) diff --git a/web/assets/css/transmission-app.scss b/web/assets/css/transmission-app.scss index 2d7ea5010..1ce3ef6d2 100644 --- a/web/assets/css/transmission-app.scss +++ b/web/assets/css/transmission-app.scss @@ -22,8 +22,6 @@ --logo-size: 64px; --pauseresume-size: 20px; --popup-top: 51px; // TODO: ugly that this is hardcoded - --progressbar-border: 1px; - --progressbar-height: 20px; --toolbar-height: 50px; /* colors related to torrent status */ @@ -108,10 +106,16 @@ --color-fg-selected: var(--dark-mode-white); --color-fg-tertiary: var(--grey-500); --color-fg-warn: var(--dark-mode-black); + --color-progressbar-fg-1: #edefff; + --color-progressbar-fg-2: #edefff; + --color-progressbar-fg-3: #edefff; --color-progressbar-paused: var(--grey-500); --color-progressbar-seed-1: var(--green-100); --color-progressbar-seed-2: var(--green-400); --color-progressbar-seed-paused: var(--grey-500); + --progress-bar-shadow-1: 1px 1px #000; + --progress-bar-shadow-2: 1px 1px #000; + --progress-bar-shadow-3: 1px 1px #000; .contrast-more { --color-bg-even: var(--black); @@ -133,6 +137,9 @@ --color-fg-tabs: var(--white); --color-fg-tertiary: var(--white); --color-fg-warn: var(--black); + --color-progressbar-fg-1: #fff; + --color-progressbar-fg-2: #fff; + --color-progressbar-fg-3: #000; --color-progressbar-background-2: var(--white); --color-progressbar-magnet: var(--yellow-300); --color-progressbar-paused: var(--grey-500); @@ -142,6 +149,7 @@ --color-progressbar-seed-paused: var(--grey-500); --color-progressbar-verify: var(--yellow-300); --color-toolbar-background: var(--black); + --progress-bar-shadow-3: 0; } } @media (prefers-color-scheme: light) { @@ -165,6 +173,9 @@ --color-fg-selected: var(--nice-grey); --color-fg-tertiary: var(--grey-500); --color-fg-warn: #cf212e; + --color-progressbar-fg-1: #303030; + --color-progressbar-fg-2: #edefff; + --color-progressbar-fg-3: #edefff; --color-progressbar-leech: var(--blue-100); --color-progressbar-magnet: var(--yellow-300); --color-progressbar-paused: var(--grey-200); @@ -173,6 +184,9 @@ --color-progressbar-seed-2: var(--green-300); --color-progressbar-seed-paused: var(--grey-200); --color-progressbar-verify: var(--yellow-300); + --progress-bar-shadow-1: 0; + --progress-bar-shadow-2: 1px 1px #000; + --progress-bar-shadow-3: 1px 1px #000; .contrast-more { --color-bg-even: var(--white); @@ -195,6 +209,9 @@ --color-fg-tertiary: var(--black); --color-fg-warn: var(--white); --color-progressbar-background-2: var(--white); + --color-progressbar-fg-1: #fff; + --color-progressbar-fg-2: #fff; + --color-progressbar-fg-3: #000; --color-progressbar-leech: var(--blue-200); --color-progressbar-magnet: var(--yellow-300); --color-progressbar-paused: var(--grey-500); @@ -204,6 +221,8 @@ --color-progressbar-seed-paused: var(--grey-500); --color-progressbar-verify: var(--yellow-300); --color-toolbar-background: var(--white); + --progress-bar-shadow-1: 1px 1px #000; + --progress-bar-shadow-3: 0; } } } @@ -619,6 +638,10 @@ a { &.paused { color: var(--color-fg-disabled); + &:not(.selected) .torrent-progress-bar { + color: var(--color-fg-primary); + } + .icon { background-color: var(--color-fg-disabled); } @@ -666,12 +689,11 @@ a { } .torrent-progress-bar { - background-repeat: no-repeat; - border-color: var(--color-border-starkest); + font-size: 14px; + position: relative; + border: 1px solid var(--color-border-starkest); border-radius: 3px; - border-style: solid; - border-width: 1px; - height: calc(var(--progressbar-height) - var(--progressbar-border) * 2); + height: 18px; &.full { flex-grow: 1; @@ -684,73 +706,91 @@ a { } &.leech { - &.queued { - background: linear-gradient( - to right, - var(--color-progressbar-queued) 0, - var(--color-progressbar-queued) var(--progress, 30%), - transparent var(--progress, 30%) - ), - no-repeat; + &.queued::before { + background: var(--color-progressbar-queued); } - background: linear-gradient( - to right, - var(--color-progressbar-leech) 0, - var(--color-progressbar-leech) var(--progress, 30%), - transparent var(--progress, 30%) - ), - no-repeat; + &::before { + background: var(--color-progressbar-leech); + color: var(--color-progressbar-fg-2); + text-shadow: var(--progress-bar-shadow-2); + } } - &.magnet { - background: linear-gradient( - to right, - var(--color-progressbar-magnet) 0, - var(--color-progressbar-magnet) var(--progress, 30%), - transparent var(--progress, 30%) - ), - no-repeat; + &.magnet::before { + background: var(--color-progressbar-magnet); + color: #000; } &.seed { - &.paused { - background-color: var(--color-progressbar-seed-paused); + &.paused::before { + background: var(--color-progressbar-seed-paused); + color: var(--color-progressbar-fg-1); + text-shadow: var(--progress-bar-shadow-1); } &:not(.paused) { - background: linear-gradient( - to right, - var(--color-progressbar-seed-1) 0, - var(--color-progressbar-seed-1) var(--progress, 30%), - var(--color-progressbar-seed-2) var(--progress, 30%) - ), - no-repeat; + &::before { + background: var(--color-progressbar-seed-1); + color: var(--color-progressbar-fg-2); + text-shadow: var(--progress-bar-shadow-2); + } + + &::after { + background: var(--color-progressbar-seed-2); + color: var(--color-progressbar-fg-3); + text-shadow: var(--progress-bar-shadow-3); + } } - &.queued { - background-color: var(--color-progressbar-seed-paused); + &.queued::before { + background-color: var(--color-progressbar-seed-1); + } + + &::before { + background-color: var(--color-progressbar-seed-1); + color: var(--color-progressbar-fg-2); + text-shadow: var(--progress-bar-shadow-2); } } - &.verify { - background: linear-gradient( - to right, - var(--color-progressbar-verify) 0, - var(--color-progressbar-verify) var(--progress, 30%), - transparent var(--progress, 30%) - ), - no-repeat; + &.verify::before { + background: var(--color-progressbar-verify); + color: #000; } - &.paused { - background: linear-gradient( - to right, - var(--color-progressbar-paused) 0, - var(--color-progressbar-paused) var(--progress, 30%), - transparent var(--progress, 30%) - ), - no-repeat; + &.paused::before { + background: var(--color-progressbar-paused); + color: var(--color-progressbar-fg-1); + text-shadow: var(--progress-bar-shadow-1); + } + + &::before, + &::after { + content: attr(data-progress); + height: 100%; + width: 100%; + position: absolute; + border-radius: 2px; + text-align: center; + } + + &::before { + clip-path: polygon( + 0 0, + var(--progress, 30%) 0, + var(--progress, 30%) 100%, + 0 100% + ); + } + + &::after { + clip-path: polygon( + var(--progress, 30%) 0, + 100% 0, + 100% 100%, + var(--progress, 30%) 100% + ); } } } diff --git a/web/src/file-row.js b/web/src/file-row.js index 3d9885b6e..d378a3848 100644 --- a/web/src/file-row.js +++ b/web/src/file-row.js @@ -34,6 +34,7 @@ export class FileRow extends EventTarget { const fmt = Formatter; const c = `${fmt.size(have)} of ${fmt.size(size)} (${fmt.percentString( pct, + 1, )}%)`; setTextContent(this.elements.progress, c); } diff --git a/web/src/formatter.js b/web/src/formatter.js index 105ddb521..7389ae908 100644 --- a/web/src/formatter.js +++ b/web/src/formatter.js @@ -94,8 +94,8 @@ export const Formatter = { }, // format a percentage to a string - percentString(x) { - const decimal_places = x < 100 ? 1 : 0; + percentString(x, decimal_places) { + decimal_places = x < 100 ? decimal_places : 0; return this._toTruncFixed(x, decimal_places); }, @@ -109,7 +109,7 @@ export const Formatter = { if (x === -2) { return '∞'; } - return this.percentString(x); + return this.percentString(x, 1); }, /** diff --git a/web/src/inspector.js b/web/src/inspector.js index 6f9aa5cb5..be1a8ce6e 100644 --- a/web/src/inspector.js +++ b/web/src/inspector.js @@ -293,7 +293,7 @@ export class Inspector extends EventTarget { const d = 100 * (sizeWhenDone ? (sizeWhenDone - leftUntilDone) / sizeWhenDone : 1); - string = fmt.percentString(d); + string = fmt.percentString(d, 1); if (unverified) { string = `${fmt.size(verified)} of ${fmt.size( @@ -320,7 +320,7 @@ export class Inspector extends EventTarget { (accumulator, t) => t.getHave() + t.getDesiredAvailable(), 0, ); - string = `${fmt.percentString((100 * available) / sizeWhenDone)}%`; + string = `${fmt.percentString((100 * available) / sizeWhenDone, 1)}%`; } setTextContent(e.info.availability, fmt.stringSanitizer(string)); diff --git a/web/src/torrent-row.js b/web/src/torrent-row.js index 82e53ea9f..ffd36235c 100644 --- a/web/src/torrent-row.js +++ b/web/src/torrent-row.js @@ -80,8 +80,10 @@ const TorrentRendererHelper = { renderProgressbar: (controller, t, progressbar) => { const info = TorrentRendererHelper.getProgressInfo(controller, t); + const pct_str = `${Formatter.percentString(info.percent, 2)}%`; progressbar.className = info.classList.join(' '); - progressbar.style.setProperty('--progress', `${info.percent.toFixed(2)}%`); + progressbar.style.setProperty('--progress', pct_str); + progressbar.dataset.progress = pct_str; }, }; @@ -151,7 +153,7 @@ export class TorrentRendererFull { if (t.isChecking()) { return [ 'Verifying local data (', - Formatter.percentString(100 * t.getRecheckProgress()), + Formatter.percentString(100 * t.getRecheckProgress(), 1), '% tested)', ].join(''); } @@ -168,7 +170,7 @@ export class TorrentRendererFull { const percent = 100 * t.getMetadataPercentComplete(); return [ `Magnetized transfer - ${MetaDataStatus} metadata (`, - Formatter.percentString(percent), + Formatter.percentString(percent, 1), '%)', ].join(''); } diff --git a/web/src/torrent.js b/web/src/torrent.js index 404dafd83..2fa15071f 100644 --- a/web/src/torrent.js +++ b/web/src/torrent.js @@ -280,7 +280,7 @@ export class Torrent extends EventTarget { return this.getDownloadSpeed() + this.getUploadSpeed(); } getPercentDoneStr() { - return Formatter.percentString(100 * this.getPercentDone()); + return Formatter.percentString(100 * this.getPercentDone(), 1); } getPercentDone() { return this.fields.percentDone;