diff --git a/src/kiri/app/init/bind.js b/src/kiri/app/init/bind.js index 0debc56e..d5d4ba3f 100644 --- a/src/kiri/app/init/bind.js +++ b/src/kiri/app/init/bind.js @@ -105,8 +105,10 @@ export function bind() { range: $('slider-center'), }, - loading: $('progress').style, - progress: $('progbar').style, + loading: $('progress-overlay')?.style, + progressOverlay: $('progress-overlay'), + progress: $('progress-ring'), + progressPct: $('progress-pct'), prostatus: $('progtxt'), selection: $('selection'), diff --git a/src/kiri/app/visuals.js b/src/kiri/app/visuals.js index a5f0af73..8b01604b 100644 --- a/src/kiri/app/visuals.js +++ b/src/kiri/app/visuals.js @@ -315,17 +315,41 @@ function applyVisualState(widget) { * @param {string} [msg] - Optional status message to display */ function setProgress(value = 0, msg) { - value = (value * 100).round(4); - api.ui.progress.width = value+'%'; - if (self.debug) { - // console.log(msg, value.round(2)); - api.ui.prostatus.style.display = 'flex'; - if (msg) { - api.ui.prostatus.innerHTML = msg; - } else { - api.ui.prostatus.innerHTML = ''; - } + const overlay = api.ui.progressOverlay; + const ring = api.ui.progress; + const pct = api.ui.progressPct; + const text = api.ui.prostatus; + + if (!overlay || !ring || !text) { + return; } + + const hasNumeric = typeof value === 'number' && Number.isFinite(value); + const indeterminate = !hasNumeric || (hasNumeric && value < 0); + const isHidden = hasNumeric && value === 0; + + if (isHidden) { + overlay.classList.add('hide'); + ring.classList.remove('indeterminate'); + if (pct) pct.innerText = ''; + text.innerText = ''; + return; + } + + overlay.classList.remove('hide'); + + if (!indeterminate) { + const clamped = Math.max(0, Math.min(1, value)); + ring.classList.remove('indeterminate'); + ring.style.setProperty('--progress-deg', `${(clamped * 360).toFixed(2)}deg`); + if (pct) pct.innerText = `${Math.round(clamped * 100)}%`; + } else { + ring.classList.add('indeterminate'); + ring.style.removeProperty('--progress-deg'); + if (pct) pct.innerText = ''; + } + + text.innerText = msg || ''; } let statsTimer; diff --git a/web/kiri/index.css b/web/kiri/index.css index 9818227a..581ca3c2 100644 --- a/web/kiri/index.css +++ b/web/kiri/index.css @@ -282,11 +282,6 @@ details[open] summary::after { .dark #alert-border:hover { background-color: rgba(255,255,255,0.7); } -.dark #progress { - background-color: #333; - border-top: 1px solid #555; - border-bottom: 1px solid #555; -} .dark #mesh-info label, .dark #mode-info label { @@ -1552,35 +1547,70 @@ details[open] summary::after { top: 0; } -#progress { - left: 0; - right: 0; - height: 6px; - min-height: 6px; - text-align: center; - background-color: rgb(220,220,220); - border-top: 1px solid #888; - border-bottom: 1px solid #888; -} -#progbar { - width: 0; - text-align: left; - position: relative; - background-color: rgb(255,90,90); -} -#progtxt { - display: none; - position: absolute; - left: 0; - right: 0; - top: 200%; - color: #888; - margin: 0 5px 0 5px; - padding: 0 5px 2px 5px; - white-space: nowrap; - flex-direction: row; +#progress-overlay { + position: fixed; + inset: 0; + z-index: 3000; + display: flex; align-items: center; justify-content: center; + pointer-events: auto; + background: rgba(0,0,0,0.08); +} + +#progress-indicator { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + min-width: 120px; + padding: 14px 18px 12px; + border: 1px solid var(--border-gray); + border-radius: 10px; + background: var(--menubar-back); + color: var(--menubar-fore); + box-shadow: 0 8px 24px rgba(0,0,0,0.25); +} + +#progress-ring { + --progress-deg: 0deg; + width: 56px; + height: 56px; + border-radius: 50%; + background: + radial-gradient(circle at center, transparent 58%, var(--menubar-back) 59%), + conic-gradient(var(--appname-blue) var(--progress-deg), rgba(128,128,128,0.25) 0); +} + +#progress-ring.indeterminate { + background: none; + border: 5px solid rgba(128,128,128,0.3); + border-top-color: var(--appname-blue); + animation: progress-spin 0.9s linear infinite; +} + +#progress-pct { + min-height: 16px; + font-size: 12px; + font-weight: 600; + color: var(--menubar-fore); +} + +#progtxt { + min-height: 16px; + max-width: 280px; + text-align: center; + font-size: 12px; + color: var(--menubar-fore); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +@keyframes progress-spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } } #dialog { diff --git a/web/kiri/index.html b/web/kiri/index.html index 5e2adbfc..06c7656d 100644 --- a/web/kiri/index.html +++ b/web/kiri/index.html @@ -56,8 +56,14 @@ - -
loading
+ +
+
+
+
+
+
+