/
vshmidt
/
label-studio
Обзор
Документация
Войти
/
vshmidt
/
label-studio
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
web/libs/editor/src/lib/AudioUltra/Visual/Loader.ts
211 строк
6 KB
bmartel
fix: FIT-31: Ensure media buffers are syncable events that keep audio and video in sync (#7633)
21 авг 2025, 12:56
Не верифицирован
21 авг 2025, 12:56
0fd582d
Код
Авторство
О чём код?
export class Loader extends HTMLElement { _loaded: number; _total: number; _initializing = false; _error = ""; constructor() { super(); this._loaded = 0; this._total = 0; this.attachShadow({ mode: "open" }); if (!this.shadowRoot) return; this.shadowRoot.innerHTML = ` <style> :host { display: flex; width: 100%; height: var(--ls-loader-height, calc(100% - var(--ls-loader-offset, 34px))); position: absolute; top: var(--ls-loader-offset, 34px); left: 0; z-index: 9999; justify-content: center; align-items: center; background-color: var(--color-neutral-background); pointer-events: none; color: var(--color-neutral-content); } :host([hidden]) { display: none; } .progress { width: 70%; } .progress-bar { overflow: hidden; display: block; position: relative; width: 100%; height: 100%; background-color: var(--ls-loader-color, rgba(65, 60, 74, 0.08)); border-radius: var(--ls-loader-progress-border-radius, 8px); height: var(--ls-loader-progress-height, 8px); } .progress-bar::after { content: ''; position: absolute; top: 0; height: 100%; width: 100%; border-radius: var(--ls-loader-progress-border-radius, 8px); background-color: var(--ls-loader-progress-color, var(--color-primary-content)); transition: transform 0.15s ease; transform-origin: left; transform: translateX(var(--ls-loader-position, -100%)); } .progress-bar-indeterminate::after { transform: translateX(0); animation: shimmer 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } .progress-bar-info { display: flex; justify-content: space-between; color: var(--color-neutral-content); } .progress-bar-text { display: flex; } .progress-bar-totals { display: flex; align-items: center; gap: 4px; } .progress-text { font-size: 9px; line-height: 16px; letter-spacing: 0.5px; font-weight: 500; margin: 0; } .error { color: var(--ls-loader-error-color, var(--color-negative-content)); } @keyframes shimmer { 50% { opacity: 0.5; } } </style> <div class="progress"> <div class="progress-bar-info"> <div class="progress-bar-text"> <h3 id="text" class="progress-text">Loading file...</h3> </div> <div class="progress-bar-totals progress-text"> <span id="loaded">0.0 MB</span><span id="percentage">(0)%</span><span>of</span><span id="total">?? MB</span> </div> </div> <div class="progress-bar"></div> </div> `; } get error() { return this._error; } set error(value: string) { this._error = value; } get loaded() { return this._loaded; } set loaded(value: number) { this._loaded = value; } get total() { return this._total; } set total(value: number) { this._total = value; } get value() { return Math.round((this.loaded / this.total) * 100); } convertBytesToMegabytes(bytes: number) { return (bytes / 1024 / 1024).toFixed(1); } update() { if (!this.shadowRoot) return; const bar = this.shadowRoot.querySelector(".progress-bar") as HTMLElement; const text = this.shadowRoot.querySelector("#text") as HTMLElement; const loadedText = this.shadowRoot.querySelector("#loaded") as HTMLElement; const totalText = this.shadowRoot.querySelector("#total") as HTMLElement; const percentageText = this.shadowRoot.querySelector("#percentage") as HTMLElement; if (!bar) return; const total = this.total; requestAnimationFrame(() => { // If an error occurred, show the error message and hide the progress bar if (this._error) { if (!text.classList.contains("error")) { text.classList.add("error"); } text.innerText = this._error; return; } // Update the progress bar for decoding of chunks if (this._initializing) { loadedText.innerText = `${this.loaded}`; totalText.innerText = `${this.total} chunks`; percentageText.innerText = `(${this.value}%)`; return; } // Indeterminate progress bar is given if no calculable total available. if (total < 0) { if (!bar.classList.contains("progress-bar-indeterminate")) bar.classList.add("progress-bar-indeterminate"); if (this.loaded > 0) { loadedText.innerText = `${this.convertBytesToMegabytes(this.loaded)} MB`; } return; } const value = this.value; // Finished loading, starting initialization if (value === 100) { this._initializing = true; if (this.total > 0) { loadedText.innerText = `${this.convertBytesToMegabytes(this.loaded)} MB`; totalText.innerText = `${this.convertBytesToMegabytes(this.total)} MB`; percentageText.innerText = `(${value}%)`; } text.innerText = "Initializing..."; bar.classList.add("progress-bar-indeterminate"); return; } // Update progress bar bar.style.setProperty("--ls-loader-position", `${value - 100}%`); if (value > 0) { percentageText.innerText = `(${value}%)`; } if (this.loaded > 0) { loadedText.innerText = `${this.convertBytesToMegabytes(this.loaded)} MB`; } if (this.total > 0) { totalText.innerText = `${this.convertBytesToMegabytes(this.total)} MB`; } }); } static get observedAttributes() { return ["hidden"]; } } customElements.define("loading-progress-bar", Loader);