Download web/progress-view.mjs from ceroomedia/DMAI-NODES: direct link, hf CLI and curl.
- Browser
- Download file 4.22 kB
-
https://huggingface.co/ceroomedia/DMAI-NODES/resolve/6e0df2b5334898f615431b75e477bab85c5ab136/web/progress-view.mjs
- Command line
-
hf download hf://ceroomedia/DMAI-NODES@6e0df2b5334898f615431b75e477bab85c5ab136/web/progress-view.mjs
-
curl -L -o progress-view.mjs https://huggingface.co/ceroomedia/DMAI-NODES/resolve/6e0df2b5334898f615431b75e477bab85c5ab136/web/progress-view.mjs
4.22 kB
| const PHASES = { | |
| idle: "", | |
| queued: "Queued", | |
| loading: "Loading", | |
| sampling: "Generating", | |
| decoding: "Decoding", | |
| saving: "Saving", | |
| complete: "Complete", | |
| error: "Failed", | |
| interrupted: "Stopped", | |
| }; | |
| const ACTIVE = new Set(["queued", "loading", "sampling", "decoding", "saving"]); | |
| export function progressPresentation(state = {}) { | |
| const phase = Object.hasOwn(PHASES, state.phase) ? state.phase : "idle"; | |
| const busy = ACTIVE.has(phase); | |
| const measured = typeof state.percent === "number" && Number.isFinite(state.percent) | |
| ? Math.max(0, Math.min(100, state.percent)) : 0; | |
| // A full border means the workflow completed, including decode and save. | |
| const percent = phase === "complete" ? 100 : Math.min(measured, 99.9); | |
| return { | |
| phase, | |
| percent: phase === "idle" ? 0 : percent, | |
| busy, | |
| label: PHASES[phase], | |
| visible: phase !== "idle", | |
| value: phase === "complete" ? 100 : Math.floor(percent), | |
| }; | |
| } | |
| export function perimeterPath(width, height) { | |
| const w = Math.max(8, Number.isFinite(width) ? width : 8); | |
| const h = Math.max(8, Number.isFinite(height) ? height : 8); | |
| const inset = 2, right = w - inset, bottom = h - inset; | |
| const r = Math.min(10, (w - 4) / 2, (h - 4) / 2); | |
| // Start at the top centre and follow the actual, rounded panel clockwise. | |
| return `M ${w / 2} ${inset} H ${right - r} Q ${right} ${inset} ${right} ${inset + r} V ${bottom - r} Q ${right} ${bottom} ${right - r} ${bottom} H ${inset + r} Q ${inset} ${bottom} ${inset} ${bottom - r} V ${inset + r} Q ${inset} ${inset} ${inset + r} ${inset} H ${w / 2}`; | |
| } | |
| export class ProgressView { | |
| constructor(panel) { | |
| this.panel = panel; | |
| this.svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); | |
| this.svg.classList.add("dmai-progress-outline"); | |
| this.svg.setAttribute("aria-hidden", "true"); | |
| this.svg.setAttribute("focusable", "false"); | |
| this.track = document.createElementNS(this.svg.namespaceURI, "path"); | |
| this.track.classList.add("dmai-progress-track"); | |
| this.stroke = document.createElementNS(this.svg.namespaceURI, "path"); | |
| this.stroke.classList.add("dmai-progress-stroke"); | |
| this.stroke.setAttribute("pathLength", "100"); | |
| this.stroke.setAttribute("stroke-dasharray", "100"); | |
| this.stroke.setAttribute("stroke-dashoffset", "100"); | |
| this.svg.append(this.track, this.stroke); | |
| panel.append(this.svg); | |
| this.readout = document.createElement("div"); | |
| this.readout.className = "dmai-progress-readout"; | |
| this.readout.setAttribute("role", "progressbar"); | |
| this.readout.setAttribute("aria-label", "Image generation progress"); | |
| this.readout.setAttribute("aria-valuemin", "0"); | |
| this.readout.setAttribute("aria-valuemax", "100"); | |
| this.label = document.createElement("span"); | |
| this.value = document.createElement("span"); | |
| this.value.className = "dmai-progress-value"; | |
| this.readout.append(this.label, this.value); | |
| this.resize = () => { | |
| const width = panel.clientWidth, height = panel.clientHeight; | |
| if (!width || !height) return; | |
| this.svg.setAttribute("viewBox", `0 0 ${width} ${height}`); | |
| const path = perimeterPath(width, height); | |
| this.track.setAttribute("d", path); | |
| this.stroke.setAttribute("d", path); | |
| }; | |
| if (typeof ResizeObserver !== "undefined") { | |
| this.observer = new ResizeObserver(this.resize); | |
| this.observer.observe(panel); | |
| } | |
| this.resize(); | |
| this.update(); | |
| } | |
| update(state) { | |
| const view = progressPresentation(state); | |
| this.panel.dataset.generationPhase = view.phase; | |
| this.panel.dataset.generating = String(view.busy); | |
| this.panel.setAttribute("aria-busy", String(view.busy)); | |
| this.svg.style.visibility = view.visible ? "visible" : "hidden"; | |
| this.stroke.style.strokeDashoffset = String(100 - view.percent); | |
| this.readout.hidden = !view.visible; | |
| this.readout.setAttribute("aria-valuenow", String(view.value)); | |
| this.readout.setAttribute("aria-valuetext", `${view.label}, ${view.value}%`); | |
| this.label.textContent = view.label; | |
| this.value.textContent = `${view.value}%`; | |
| return view; | |
| } | |
| dispose() { | |
| this.observer?.disconnect(); | |
| this.svg.remove(); | |
| this.readout.remove(); | |
| } | |
| } | |