WebUI: Convert 'Progress Bar' class to a custom element

This commit is contained in:
tehcneko 2025-05-25 13:04:14 +08:00
commit b893f87531
2 changed files with 76 additions and 152 deletions

View file

@ -65,7 +65,6 @@ window.qBittorrent.DynamicTable ??= (() => {
}; };
let DynamicTableHeaderContextMenuClass = null; let DynamicTableHeaderContextMenuClass = null;
let progressColumnWidth = -1;
class DynamicTable { class DynamicTable {
setup(dynamicTableDivId, dynamicTableFixedHeaderDivId, contextMenu, useVirtualList = false) { setup(dynamicTableDivId, dynamicTableFixedHeaderDivId, contextMenu, useVirtualList = false) {
@ -1358,34 +1357,14 @@ window.qBittorrent.DynamicTable ??= (() => {
const div = td.firstElementChild; const div = td.firstElementChild;
if (div !== null) { if (div !== null) {
if (td.resized) {
td.resized = false;
div.setWidth(progressColumnWidth - 5);
}
if (div.getValue() !== progressFormatted) if (div.getValue() !== progressFormatted)
div.setValue(progressFormatted); div.setValue(progressFormatted);
} }
else { else {
if (progressColumnWidth < 0) td.append(new window.qBittorrent.ProgressBar.ProgressBar(progressFormatted));
progressColumnWidth = td.offsetWidth;
td.append(new window.qBittorrent.ProgressBar.ProgressBar(progressFormatted, {
width: progressColumnWidth - 5
}));
td.resized = false;
} }
}; };
this.columns["progress"].staticWidth = 100; this.columns["progress"].staticWidth = 100;
this.columns["progress"].onResize = function(columnName) {
const pos = this.getColumnPos(columnName);
progressColumnWidth = -1;
for (const tr of this.getTrs()) {
const td = this.getRowCells(tr)[pos];
if (progressColumnWidth < 0)
progressColumnWidth = td.offsetWidth;
td.resized = true;
this.columns[columnName].updateTd(td, this.getRow(tr.rowId));
}
}.bind(this);
// num_seeds // num_seeds
this.columns["num_seeds"].updateTd = function(td, row) { this.columns["num_seeds"].updateTd = function(td, row) {
@ -2881,14 +2860,10 @@ window.qBittorrent.DynamicTable ??= (() => {
const value = Number(this.getRowValue(row)); const value = Number(this.getRowValue(row));
const progressBar = td.firstElementChild; const progressBar = td.firstElementChild;
if (progressBar === null) { if (progressBar === null)
td.append(new window.qBittorrent.ProgressBar.ProgressBar(value, { td.append(new window.qBittorrent.ProgressBar.ProgressBar(value));
width: 80 else
}));
}
else {
progressBar.setValue(value); progressBar.setValue(value);
}
}; };
this.columns["progress"].staticWidth = 100; this.columns["progress"].staticWidth = 100;
@ -3789,34 +3764,14 @@ window.qBittorrent.DynamicTable ??= (() => {
const div = td.firstElementChild; const div = td.firstElementChild;
if (div !== null) { if (div !== null) {
if (td.resized) {
td.resized = false;
div.setWidth(progressColumnWidth - 5);
}
if (div.getValue() !== progress) if (div.getValue() !== progress)
div.setValue(progress); div.setValue(progress);
} }
else { else {
if (progressColumnWidth < 0) td.append(new window.qBittorrent.ProgressBar.ProgressBar(progress));
progressColumnWidth = td.offsetWidth;
td.append(new window.qBittorrent.ProgressBar.ProgressBar(progress, {
width: progressColumnWidth - 5
}));
td.resized = false;
} }
}; };
this.columns["progress"].staticWidth = 100; this.columns["progress"].staticWidth = 100;
this.columns["progress"].onResize = function(columnName) {
const pos = this.getColumnPos(columnName);
progressColumnWidth = -1;
for (const tr of this.getTrs()) {
const td = this.getRowCells(tr)[pos];
if (progressColumnWidth < 0)
progressColumnWidth = td.offsetWidth;
td.resized = true;
this.columns[columnName].updateTd(td, this.getRow(tr.rowId));
}
}.bind(this);
// piece_size // piece_size
this.columns["piece_size"].updateTd = function(td, row) { this.columns["piece_size"].updateTd = function(td, row) {

View file

@ -36,124 +36,93 @@ window.qBittorrent.ProgressBar ??= (() => {
}; };
}; };
let progressBars = 0; class ProgressBar extends HTMLElement {
const ProgressBar = new Class({ static #progressBarUniqueId = 0;
initialize: (value, parameters) => {
const vals = { #value;
id: `progressbar_${progressBars++}`, #styles;
value: [value, 0].pick(), #id = ++ProgressBar.#progressBarUniqueId;
width: 0, #light;
height: 0, #dark;
constructor(value, styles = {}) {
super();
this.setValue(value);
this.#styles = {
height: 12,
darkbg: "var(--color-background-blue)", darkbg: "var(--color-background-blue)",
darkfg: "var(--color-text-white)", darkfg: "var(--color-text-white)",
lightbg: "var(--color-background-default)", lightbg: "var(--color-background-default)",
lightfg: "var(--color-text-default)" lightfg: "var(--color-text-default)",
...styles
}; };
if (parameters && (typeOf(parameters) === "object"))
Object.append(vals, parameters);
if (vals.height < 12)
vals.height = 12;
const obj = document.createElement("div"); this.#dark = document.createElement("div");
obj.id = vals.id; this.#dark.style.width = "100%";
obj.className = "progressbar_wrapper"; this.#dark.style.height = `${this.#styles.height}px`;
obj.style.border = "1px solid var(--color-border-default)"; this.#dark.style.background = this.#styles.darkbg;
obj.style.boxSizing = "content-box"; this.#dark.style.boxSizing = "content-box";
obj.style.width = `${vals.width}px`; this.#dark.style.color = this.#styles.darkfg;
obj.style.height = `${vals.height}px`; this.#dark.style.position = "absolute";
obj.style.position = "relative"; this.#dark.style.textAlign = "center";
obj.style.margin = "0 auto"; this.#dark.style.left = "0";
obj.vals = vals; this.#dark.style.top = "0";
obj.vals.value = [value, 0].pick(); this.#dark.style.lineHeight = `${this.#styles.height}px`;
const dark = document.createElement("div"); this.#light = document.createElement("div");
dark.id = `${vals.id}_dark`; this.#light.style.width = "100%";
dark.className = "progressbar_dark"; this.#light.style.height = `${this.#styles.height}px`;
dark.style.width = `${vals.width}px`; this.#light.style.background = this.#styles.lightbg;
dark.style.height = `${vals.height}px`; this.#light.style.boxSizing = "content-box";
dark.style.background = vals.darkbg; this.#light.style.color = this.#styles.lightfg;
dark.style.boxSizing = "content-box"; this.#light.style.position = "absolute";
dark.style.color = vals.darkfg; this.#light.style.textAlign = "center";
dark.style.position = "absolute"; this.#light.style.left = "0";
dark.style.textAlign = "center"; this.#light.style.top = "0";
dark.style.left = "0"; this.#light.style.lineHeight = `${this.#styles.height}px`;
dark.style.top = "0";
dark.style.lineHeight = `${vals.height}px`;
obj.vals.dark = dark; this.attachShadow({ mode: "open" });
this.shadowRoot.host.id = this.#id;
const light = document.createElement("div"); this.shadowRoot.host.style.display = "block";
light.id = `${vals.id}_light`; this.shadowRoot.host.style.border = "1px solid var(--color-border-default)";
light.className = "progressbar_light"; this.shadowRoot.host.style.boxSizing = "content-box";
light.style.width = `${vals.width}px`; this.shadowRoot.host.style.height = `${this.#styles.height}px`;
light.style.height = `${vals.height}px`; this.shadowRoot.host.style.position = "relative";
light.style.background = vals.lightbg; this.shadowRoot.host.style.margin = "0 auto";
light.style.boxSizing = "content-box"; this.shadowRoot.appendChild(this.#dark);
light.style.color = vals.lightfg; this.shadowRoot.appendChild(this.#light);
light.style.position = "absolute";
light.style.textAlign = "center";
light.style.left = "0";
light.style.top = "0";
light.style.lineHeight = `${vals.height}px`;
obj.vals.light = light;
obj.appendChild(obj.vals.dark);
obj.appendChild(obj.vals.light);
obj.getValue = ProgressBar_getValue;
obj.setValue = ProgressBar_setValue;
obj.setWidth = ProgressBar_setWidth;
if (vals.width)
obj.setValue(vals.value);
else
setTimeout(ProgressBar_checkForParent, 0, obj.id);
return obj;
} }
});
function ProgressBar_getValue() { connectedCallback() {
return this.vals.value; this.#refresh();
} }
function ProgressBar_setValue(value) { getValue() {
value = Number(value); return this.#value;
if (Number.isNaN(value)) }
value = 0;
value = Math.min(Math.max(value, 0), 100);
this.vals.value = value;
const displayedValue = `${window.qBittorrent.Misc.toFixedPointString(value, 1)}%`; setValue(value) {
this.vals.dark.textContent = displayedValue; value = Number(value);
this.vals.light.textContent = displayedValue; if (Number.isNaN(value))
value = 0;
this.#value = Math.min(Math.max(value, 0), 100);
this.#refresh();
}
const r = Number(this.vals.width * (value / 100)); #refresh() {
this.vals.dark.style.clipPath = `inset(0 calc(100% - ${r}px) 0 0)`; if (!this.isConnected)
this.vals.light.style.clipPath = `inset(0 0 0 ${r}px)`; return;
}
function ProgressBar_setWidth(value) { const displayedValue = `${window.qBittorrent.Misc.toFixedPointString(this.#value, 1)}%`;
if (this.vals.width !== value) { this.#dark.textContent = displayedValue;
this.vals.width = value; this.#light.textContent = displayedValue;
this.style.width = `${value}px`;
this.vals.dark.style.width = `${value}px`; this.#dark.style.clipPath = `inset(0 ${100 - this.#value}% 0 0)`;
this.vals.light.style.width = `${value}px`; this.#light.style.clipPath = `inset(0 0 0 ${this.#value}%)`;
this.setValue(this.vals.value);
} }
} }
const ProgressBar_checkForParent = (id) => { customElements.define("progress-bar", ProgressBar);
const obj = document.getElementById(id);
if (!obj)
return;
if (!obj.parentNode)
return setTimeout(ProgressBar_checkForParent, 100, id);
obj.style.width = "100%";
const w = obj.offsetWidth;
obj.vals.dark.style.width = `${w}px`;
obj.vals.light.style.width = `${w}px`;
obj.vals.width = w;
obj.setValue(obj.vals.value);
};
return exports(); return exports();
})(); })();